Mesh: Rewrite split edges algorithm #110661
|
@ -266,6 +266,9 @@ class NewGeometryNodeGroupTool(Operator):
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not context.space_data:
|
||||
# Does not exist if the search menu is called while the cursor is outside the Blender window.
|
||||
return False
|
||||
return context.space_data.type == 'NODE_EDITOR' and context.space_data.geometry_nodes_type == 'TOOL'
|
||||
|
||||
def execute(self, context):
|
||||
|
|
|
@ -1033,6 +1033,29 @@ void gather_attributes(const AttributeAccessor src_attributes,
|
|||
});
|
||||
}
|
||||
|
||||
static bool indices_are_range(const Span<int> indices, const IndexRange range)
|
||||
{
|
||||
if (indices.size() != range.size()) {
|
||||
return false;
|
||||
}
|
||||
return threading::parallel_reduce(
|
||||
range,
|
||||
4096,
|
||||
true,
|
||||
[&](const IndexRange range, const bool init) {
|
||||
if (!init) {
|
||||
return false;
|
||||
}
|
||||
for (const int i : range) {
|
||||
if (indices[i] != i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[](const bool a, const bool b) { return a && b; });
|
||||
}
|
||||
|
||||
void gather_attributes(const AttributeAccessor src_attributes,
|
||||
const eAttrDomain domain,
|
||||
const AnonymousAttributePropagationInfo &propagation_info,
|
||||
|
@ -1040,26 +1063,31 @@ void gather_attributes(const AttributeAccessor src_attributes,
|
|||
const Span<int> indices,
|
||||
MutableAttributeAccessor dst_attributes)
|
||||
{
|
||||
src_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
|
||||
if (meta_data.domain != domain) {
|
||||
if (indices_are_range(indices, IndexRange(src_attributes.domain_size(domain)))) {
|
||||
copy_attributes(src_attributes, domain, propagation_info, skip, dst_attributes);
|
||||
}
|
||||
else {
|
||||
src_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
|
||||
if (meta_data.domain != domain) {
|
||||
return true;
|
||||
}
|
||||
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
|
||||
return true;
|
||||
}
|
||||
if (skip.contains(id.name())) {
|
||||
return true;
|
||||
}
|
||||
const bke::GAttributeReader src = src_attributes.lookup(id, domain);
|
||||
bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
|
||||
id, domain, meta_data.data_type);
|
||||
if (!dst) {
|
||||
return true;
|
||||
}
|
||||
attribute_math::gather(src.varray, indices, dst.span);
|
||||
dst.finish();
|
||||
return true;
|
||||
}
|
||||
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
|
||||
return true;
|
||||
}
|
||||
if (skip.contains(id.name())) {
|
||||
return true;
|
||||
}
|
||||
const bke::GAttributeReader src = src_attributes.lookup(id, domain);
|
||||
bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
|
||||
id, domain, meta_data.data_type);
|
||||
if (!dst) {
|
||||
return true;
|
||||
}
|
||||
attribute_math::gather(src.varray, indices, dst.span);
|
||||
dst.finish();
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -653,18 +653,20 @@ static const EnumPropertyItem *bone_collection_enum_items(bContext *C,
|
|||
PropertyRNA * /*prop*/,
|
||||
bool *r_free)
|
||||
{
|
||||
Object *obpose = ED_pose_object_from_context(C);
|
||||
bArmature *arm = static_cast<bArmature *>(obpose->data);
|
||||
|
||||
EnumPropertyItem *item = nullptr, item_tmp = {0};
|
||||
int totitem = 0;
|
||||
int bcoll_index = 0;
|
||||
|
||||
LISTBASE_FOREACH_INDEX (BoneCollection *, bcoll, &arm->collections, bcoll_index) {
|
||||
item_tmp.identifier = bcoll->name;
|
||||
item_tmp.name = bcoll->name;
|
||||
item_tmp.value = bcoll_index;
|
||||
RNA_enum_item_add(&item, &totitem, &item_tmp);
|
||||
if (C) {
|
||||
Object *obpose = ED_pose_object_from_context(C);
|
||||
bArmature *arm = static_cast<bArmature *>(obpose->data);
|
||||
|
||||
LISTBASE_FOREACH_INDEX (BoneCollection *, bcoll, &arm->collections, bcoll_index) {
|
||||
item_tmp.identifier = bcoll->name;
|
||||
item_tmp.name = bcoll->name;
|
||||
item_tmp.value = bcoll_index;
|
||||
RNA_enum_item_add(&item, &totitem, &item_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
RNA_enum_item_add_separator(&item, &totitem);
|
||||
|
|
|
@ -20,26 +20,6 @@
|
|||
|
||||
namespace blender::geometry {
|
||||
|
||||
static bool indices_are_full_ordered_copy(const Span<int> indices)
|
||||
{
|
||||
return threading::parallel_reduce(
|
||||
indices.index_range(),
|
||||
4096,
|
||||
true,
|
||||
[&](const IndexRange range, const bool init) {
|
||||
if (!init) {
|
||||
return false;
|
||||
}
|
||||
for (const int i : range) {
|
||||
if (indices[i] != i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[](const bool a, const bool b) { return a && b; });
|
||||
}
|
||||
|
||||
BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
|
||||
const bke::AttributeAccessor &mesh_attributes,
|
||||
const Span<int> vert_indices,
|
||||
|
@ -58,24 +38,23 @@ BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
|
|||
curves.cyclic_for_write().slice(cyclic_curves).fill(true);
|
||||
}
|
||||
|
||||
const int src_total_points = mesh_attributes.domain_size(ATTR_DOMAIN_POINT);
|
||||
const bool share_vert_data = vert_indices.size() == src_total_points &&
|
||||
indices_are_full_ordered_copy(vert_indices);
|
||||
if (share_vert_data) {
|
||||
bke::copy_attributes(
|
||||
mesh_attributes, ATTR_DOMAIN_POINT, propagation_info, {}, curves_attributes);
|
||||
/* Don't copy attributes that are built-in on meshes but not on curves. */
|
||||
Set<std::string> skip;
|
||||
for (const bke::AttributeIDRef &id : mesh_attributes.all_ids()) {
|
||||
if (mesh_attributes.is_builtin(id) && !curves_attributes.is_builtin(id)) {
|
||||
skip.add(id.name());
|
||||
}
|
||||
}
|
||||
|
||||
bke::gather_attributes(
|
||||
mesh_attributes, ATTR_DOMAIN_POINT, propagation_info, skip, vert_indices, curves_attributes);
|
||||
|
||||
mesh_attributes.for_all(
|
||||
[&](const bke::AttributeIDRef &id, const bke::AttributeMetaData meta_data) {
|
||||
if (share_vert_data) {
|
||||
if (meta_data.domain == ATTR_DOMAIN_POINT) {
|
||||
return true;
|
||||
}
|
||||
if (meta_data.domain == ATTR_DOMAIN_POINT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mesh_attributes.is_builtin(id) && !curves_attributes.is_builtin(id)) {
|
||||
/* Don't copy attributes that are built-in on meshes but not on curves. */
|
||||
if (skip.contains(id.name())) {
|
||||
return true;
|
||||
}
|
||||
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
|
||||
|
@ -90,12 +69,7 @@ BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
|
|||
}
|
||||
bke::GSpanAttributeWriter dst = curves_attributes.lookup_or_add_for_write_only_span(
|
||||
id, ATTR_DOMAIN_POINT, meta_data.data_type);
|
||||
if (share_vert_data) {
|
||||
array_utils::copy(*src, dst.span);
|
||||
}
|
||||
else {
|
||||
bke::attribute_math::gather(*src, vert_indices, dst.span);
|
||||
}
|
||||
bke::attribute_math::gather(*src, vert_indices, dst.span);
|
||||
dst.finish();
|
||||
return true;
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue