diff options
Diffstat (limited to 'source/blender/nodes')
66 files changed, 547 insertions, 485 deletions
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index c2dd1cd3ab5..0d5ba6cf5db 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -5,7 +5,6 @@ #include "FN_field.hh" #include "FN_multi_function_builder.hh" -#include "BKE_attribute_access.hh" #include "BKE_geometry_fields.hh" #include "BKE_geometry_set.hh" @@ -20,16 +19,22 @@ struct ModifierData; namespace blender::nodes { using bke::AnonymousAttributeFieldInput; +using bke::AttributeAccessor; using bke::AttributeFieldInput; using bke::AttributeIDRef; +using bke::AttributeKind; +using bke::AttributeMetaData; +using bke::AttributeReader; +using bke::AttributeWriter; +using bke::GAttributeReader; +using bke::GAttributeWriter; using bke::GeometryComponentFieldContext; using bke::GeometryFieldInput; -using bke::OutputAttribute; -using bke::OutputAttribute_Typed; -using bke::ReadAttributeLookup; +using bke::GSpanAttributeWriter; +using bke::MutableAttributeAccessor; +using bke::SpanAttributeWriter; using bke::StrongAnonymousAttributeID; using bke::WeakAnonymousAttributeID; -using bke::WriteAttributeLookup; using fn::Field; using fn::FieldContext; using fn::FieldEvaluator; diff --git a/source/blender/nodes/geometry/nodes/node_geo_accumulate_field.cc b/source/blender/nodes/geometry/nodes/node_geo_accumulate_field.cc index be7b3446125..58fbfb5a000 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_accumulate_field.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_accumulate_field.cc @@ -217,16 +217,20 @@ template<typename T> class AccumulateFieldInput final : public GeometryFieldInpu IndexMask UNUSED(mask)) const final { const GeometryComponentFieldContext field_context{component, source_domain_}; - const int domain_num = component.attribute_domain_num(field_context.domain()); + const int domain_size = component.attribute_domain_size(field_context.domain()); + if (domain_size == 0) { + return {}; + } + const AttributeAccessor attributes = *component.attributes(); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.add(input_); evaluator.add(group_index_); evaluator.evaluate(); const VArray<T> values = evaluator.get_evaluated<T>(0); const VArray<int> group_indices = evaluator.get_evaluated<int>(1); - Array<T> accumulations_out(domain_num); + Array<T> accumulations_out(domain_size); if (group_indices.is_single()) { T accumulation = T(); @@ -261,7 +265,7 @@ template<typename T> class AccumulateFieldInput final : public GeometryFieldInpu } } - return component.attribute_try_adapt_domain<T>( + return attributes.adapt_domain<T>( VArray<T>::ForContainer(std::move(accumulations_out)), source_domain_, domain); } @@ -303,9 +307,13 @@ template<typename T> class TotalFieldInput final : public GeometryFieldInput { IndexMask UNUSED(mask)) const final { const GeometryComponentFieldContext field_context{component, source_domain_}; - const int domain_num = component.attribute_domain_num(field_context.domain()); + const int domain_size = component.attribute_domain_size(field_context.domain()); + if (domain_size == 0) { + return {}; + } + const AttributeAccessor attributes = *component.attributes(); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.add(input_); evaluator.add(group_index_); evaluator.evaluate(); @@ -317,10 +325,10 @@ template<typename T> class TotalFieldInput final : public GeometryFieldInput { for (const int i : values.index_range()) { accumulation = values[i] + accumulation; } - return VArray<T>::ForSingle(accumulation, domain_num); + return VArray<T>::ForSingle(accumulation, domain_size); } - Array<T> accumulations_out(domain_num); + Array<T> accumulations_out(domain_size); Map<int, T> accumulations; for (const int i : values.index_range()) { T &value = accumulations.lookup_or_add_default(group_indices[i]); @@ -330,7 +338,7 @@ template<typename T> class TotalFieldInput final : public GeometryFieldInput { accumulations_out[i] = accumulations.lookup(group_indices[i]); } - return component.attribute_try_adapt_domain<T>( + return attributes.adapt_domain<T>( VArray<T>::ForContainer(std::move(accumulations_out)), source_domain_, domain); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc index 496fb081d6b..9f317075bb5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc @@ -111,19 +111,26 @@ static void try_capture_field_on_geometry(GeometryComponent &component, const eAttrDomain domain, const GField &field) { + const int domain_size = component.attribute_domain_size(domain); + if (domain_size == 0) { + return; + } GeometryComponentFieldContext field_context{component, domain}; - const int domain_num = component.attribute_domain_num(domain); - const IndexMask mask{IndexMask(domain_num)}; + MutableAttributeAccessor attributes = *component.attributes_for_write(); + const IndexMask mask{IndexMask(domain_size)}; const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(field.cpp_type()); - OutputAttribute output_attribute = component.attribute_try_get_for_output_only( + GAttributeWriter output_attribute = attributes.lookup_or_add_for_write( attribute_id, domain, data_type); + if (!output_attribute) { + return; + } fn::FieldEvaluator evaluator{field_context, &mask}; - evaluator.add_with_destination(field, output_attribute.varray()); + evaluator.add_with_destination(field, output_attribute.varray); evaluator.evaluate(); - output_attribute.save(); + output_attribute.finish(); } static StringRefNull identifier_suffix(eCustomDataType data_type) diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc index 8ab0eb678e7..7e4904a7a6a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_domain_size.cc @@ -72,11 +72,11 @@ static void node_geo_exec(GeoNodeExecParams params) case GEO_COMPONENT_TYPE_MESH: { if (geometry_set.has_mesh()) { const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>(); - params.set_output("Point Count", component->attribute_domain_num(ATTR_DOMAIN_POINT)); - params.set_output("Edge Count", component->attribute_domain_num(ATTR_DOMAIN_EDGE)); - params.set_output("Face Count", component->attribute_domain_num(ATTR_DOMAIN_FACE)); - params.set_output("Face Corner Count", - component->attribute_domain_num(ATTR_DOMAIN_CORNER)); + const AttributeAccessor attributes = *component->attributes(); + params.set_output("Point Count", attributes.domain_size(ATTR_DOMAIN_POINT)); + params.set_output("Edge Count", attributes.domain_size(ATTR_DOMAIN_EDGE)); + params.set_output("Face Count", attributes.domain_size(ATTR_DOMAIN_FACE)); + params.set_output("Face Corner Count", attributes.domain_size(ATTR_DOMAIN_CORNER)); } else { params.set_default_remaining_outputs(); @@ -86,8 +86,9 @@ static void node_geo_exec(GeoNodeExecParams params) case GEO_COMPONENT_TYPE_CURVE: { if (geometry_set.has_curves()) { const CurveComponent *component = geometry_set.get_component_for_read<CurveComponent>(); - params.set_output("Point Count", component->attribute_domain_num(ATTR_DOMAIN_POINT)); - params.set_output("Spline Count", component->attribute_domain_num(ATTR_DOMAIN_CURVE)); + const AttributeAccessor attributes = *component->attributes(); + params.set_output("Point Count", attributes.domain_size(ATTR_DOMAIN_POINT)); + params.set_output("Spline Count", attributes.domain_size(ATTR_DOMAIN_CURVE)); } else { params.set_default_remaining_outputs(); @@ -98,7 +99,7 @@ static void node_geo_exec(GeoNodeExecParams params) if (geometry_set.has_pointcloud()) { const PointCloudComponent *component = geometry_set.get_component_for_read<PointCloudComponent>(); - params.set_output("Point Count", component->attribute_domain_num(ATTR_DOMAIN_POINT)); + params.set_output("Point Count", component->attributes()->domain_size(ATTR_DOMAIN_POINT)); } else { params.set_default_remaining_outputs(); @@ -109,7 +110,8 @@ static void node_geo_exec(GeoNodeExecParams params) if (geometry_set.has_instances()) { const InstancesComponent *component = geometry_set.get_component_for_read<InstancesComponent>(); - params.set_output("Instance Count", component->attribute_domain_num(ATTR_DOMAIN_INSTANCE)); + params.set_output("Instance Count", + component->attributes()->domain_size(ATTR_DOMAIN_INSTANCE)); } else { params.set_default_remaining_outputs(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc index 08e72dae8f6..34e28e50c81 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_statistic.cc @@ -195,9 +195,13 @@ static void node_geo_exec(GeoNodeExecParams params) const Field<float> input_field = params.get_input<Field<float>>("Attribute"); Vector<float> data; for (const GeometryComponent *component : components) { - if (component->attribute_domain_supported(domain)) { + const std::optional<AttributeAccessor> attributes = component->attributes(); + if (!attributes.has_value()) { + continue; + } + if (attributes->domain_supported(domain)) { GeometryComponentFieldContext field_context{*component, domain}; - const int domain_num = component->attribute_domain_num(domain); + const int domain_num = attributes->domain_size(domain); fn::FieldEvaluator data_evaluator{field_context, domain_num}; data_evaluator.add(input_field); @@ -273,9 +277,13 @@ static void node_geo_exec(GeoNodeExecParams params) const Field<float3> input_field = params.get_input<Field<float3>>("Attribute_001"); Vector<float3> data; for (const GeometryComponent *component : components) { - if (component->attribute_domain_supported(domain)) { + const std::optional<AttributeAccessor> attributes = component->attributes(); + if (!attributes.has_value()) { + continue; + } + if (attributes->domain_supported(domain)) { GeometryComponentFieldContext field_context{*component, domain}; - const int domain_num = component->attribute_domain_num(domain); + const int domain_num = attributes->domain_size(domain); fn::FieldEvaluator data_evaluator{field_context, domain_num}; data_evaluator.add(input_field); diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index 81cce1fc5da..69938f3e447 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -154,17 +154,15 @@ static void node_geo_exec(GeoNodeExecParams params) /* Store intersecting edges in attribute. */ if (attribute_outputs.intersecting_edges_id) { - MeshComponent mesh_component; - mesh_component.replace(result, GeometryOwnershipType::Editable); - OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>( + MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*result); + SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_only_span<bool>( attribute_outputs.intersecting_edges_id.get(), ATTR_DOMAIN_EDGE); - MutableSpan<bool> selection = attribute.as_span(); - selection.fill(false); + + selection.span.fill(false); for (const int i : intersecting_edges) { - selection[i] = true; + selection.span[i] = true; } - - attribute.save(); + selection.finish(); params.set_output( "Intersecting Edges", diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index 045206d04cd..489b618b8be 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -143,7 +143,8 @@ static Mesh *compute_hull(const GeometrySet &geometry_set) if (geometry_set.has_mesh()) { count++; const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>(); - total_num += component->attribute_domain_num(ATTR_DOMAIN_POINT); + const Mesh *mesh = component->get_for_read(); + total_num += mesh->totvert; } if (geometry_set.has_pointcloud()) { @@ -151,10 +152,9 @@ static Mesh *compute_hull(const GeometrySet &geometry_set) span_count++; const PointCloudComponent *component = geometry_set.get_component_for_read<PointCloudComponent>(); - VArray<float3> varray = component->attribute_get_for_read<float3>( - "position", ATTR_DOMAIN_POINT, {0, 0, 0}); - total_num += varray.size(); - positions_span = varray.get_internal_span(); + const PointCloud *pointcloud = component->get_for_read(); + positions_span = {reinterpret_cast<const float3 *>(pointcloud->co), pointcloud->totpoint}; + total_num += pointcloud->totpoint; } if (geometry_set.has_curves()) { @@ -181,8 +181,8 @@ static Mesh *compute_hull(const GeometrySet &geometry_set) if (geometry_set.has_mesh()) { const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>(); - VArray<float3> varray = component->attribute_get_for_read<float3>( - "position", ATTR_DOMAIN_POINT, {0, 0, 0}); + const VArray<float3> varray = component->attributes()->lookup<float3>("position", + ATTR_DOMAIN_POINT); varray.materialize(positions.as_mutable_span().slice(offset, varray.size())); offset += varray.size(); } @@ -190,8 +190,8 @@ static Mesh *compute_hull(const GeometrySet &geometry_set) if (geometry_set.has_pointcloud()) { const PointCloudComponent *component = geometry_set.get_component_for_read<PointCloudComponent>(); - VArray<float3> varray = component->attribute_get_for_read<float3>( - "position", ATTR_DOMAIN_POINT, {0, 0, 0}); + const VArray<float3> varray = component->attributes()->lookup<float3>("position", + ATTR_DOMAIN_POINT); varray.materialize(positions.as_mutable_span().slice(offset, varray.size())); offset += varray.size(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc index fb8a488ddae..e200350dc18 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc @@ -581,8 +581,8 @@ static void calculate_curve_fillet(GeometrySet &geometry_set, CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>(); GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_POINT); - fn::FieldEvaluator field_evaluator{field_context, domain_num}; + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT); + fn::FieldEvaluator field_evaluator{field_context, domain_size}; field_evaluator.add(radius_field); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc index 91ba5f2845f..286d9993d0e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc @@ -61,13 +61,13 @@ static Curves *create_star_curve(const float inner_radius, static void create_selection_output(CurveComponent &component, StrongAnonymousAttributeID &r_attribute) { - OutputAttribute_Typed<bool> attribute = component.attribute_try_get_for_output_only<bool>( - r_attribute.get(), ATTR_DOMAIN_POINT); - MutableSpan<bool> selection = attribute.as_span(); - for (int i : selection.index_range()) { - selection[i] = i % 2 == 0; + SpanAttributeWriter<bool> selection = + component.attributes_for_write()->lookup_or_add_for_write_only_span<bool>(r_attribute.get(), + ATTR_DOMAIN_POINT); + for (int i : selection.span.index_range()) { + selection.span[i] = i % 2 == 0; } - attribute.save(); + selection.finish(); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc index 64a174df599..de29735bd2d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc @@ -27,9 +27,9 @@ static void node_geo_exec(GeoNodeExecParams params) Field<bool> selection_field = params.get_input<Field<bool>>("Selection"); const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>(); GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_CURVE}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_CURVE); + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_CURVE); - fn::FieldEvaluator selection_evaluator{field_context, domain_num}; + fn::FieldEvaluator selection_evaluator{field_context, domain_size}; selection_evaluator.add(selection_field); selection_evaluator.evaluate(); const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc index 469d8d8d13b..f7ba724c377 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc @@ -98,8 +98,8 @@ static void node_geo_exec(GeoNodeExecParams params) } has_curves = true; const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>(); - if (!component.attribute_exists("handle_type_left") || - !component.attribute_exists("handle_type_right")) { + const AttributeAccessor attributes = *component.attributes(); + if (!attributes.contains("handle_type_left") || !attributes.contains("handle_type_right")) { return; } has_bezier = true; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index 7d83b4b3ecb..6c4fb2e0855 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -126,19 +126,18 @@ static GMutableSpan ensure_point_attribute(PointCloudComponent &points, const AttributeIDRef &attribute_id, const eCustomDataType data_type) { - points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault()); - WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id); - BLI_assert(attribute); - return attribute.varray.get_internal_span(); + return points.attributes_for_write() + ->lookup_or_add_for_write(attribute_id, ATTR_DOMAIN_POINT, data_type) + .varray.get_internal_span(); } template<typename T> static MutableSpan<T> ensure_point_attribute(PointCloudComponent &points, const AttributeIDRef &attribute_id) { - GMutableSpan attribute = ensure_point_attribute( - points, attribute_id, bke::cpp_type_to_custom_data_type(CPPType::get<T>())); - return attribute.typed<T>(); + return points.attributes_for_write() + ->lookup_or_add_for_write<T>(attribute_id, ATTR_DOMAIN_POINT) + .varray.get_internal_span(); } namespace { diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc index 2b90428acb1..00a79168087 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -506,9 +506,9 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set, CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>(); GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_CURVE}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_CURVE); + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_CURVE); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.add(start_field); evaluator.add(end_field); evaluator.evaluate(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc index 60b5f0383ca..ab7ddfa71f1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_on_surface.cc @@ -252,10 +252,8 @@ static void node_geo_exec(GeoNodeExecParams params) BKE_mesh_wrapper_ensure_mdata(surface_mesh_eval); - MeshComponent mesh_eval; - mesh_eval.replace(surface_mesh_eval, GeometryOwnershipType::ReadOnly); - MeshComponent mesh_orig; - mesh_orig.replace(surface_mesh_orig, GeometryOwnershipType::ReadOnly); + const AttributeAccessor mesh_attributes_eval = bke::mesh_attributes(*surface_mesh_eval); + const AttributeAccessor mesh_attributes_orig = bke::mesh_attributes(*surface_mesh_orig); Curves &curves_id = *curves_geometry.get_curves_for_write(); CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry); @@ -266,7 +264,7 @@ static void node_geo_exec(GeoNodeExecParams params) params.error_message_add(NodeWarningType::Error, message); return; } - if (!mesh_eval.attribute_exists(uv_map_name)) { + if (!mesh_attributes_eval.contains(uv_map_name)) { pass_through_input(); char *message = BLI_sprintfN(TIP_("Evaluated surface missing UV map: %s."), uv_map_name.c_str()); @@ -274,7 +272,7 @@ static void node_geo_exec(GeoNodeExecParams params) MEM_freeN(message); return; } - if (!mesh_orig.attribute_exists(uv_map_name)) { + if (!mesh_attributes_orig.contains(uv_map_name)) { pass_through_input(); char *message = BLI_sprintfN(TIP_("Original surface missing UV map: %s."), uv_map_name.c_str()); @@ -282,7 +280,7 @@ static void node_geo_exec(GeoNodeExecParams params) MEM_freeN(message); return; } - if (!mesh_eval.attribute_exists(rest_position_name)) { + if (!mesh_attributes_eval.contains(rest_position_name)) { pass_through_input(); params.error_message_add(NodeWarningType::Error, TIP_("Evaluated surface missing attribute: rest_position.")); @@ -294,12 +292,12 @@ static void node_geo_exec(GeoNodeExecParams params) TIP_("Curves are not attached to any UV map.")); return; } - const VArraySpan<float2> uv_map_orig = mesh_orig.attribute_get_for_read<float2>( - uv_map_name, ATTR_DOMAIN_CORNER, {0.0f, 0.0f}); - const VArraySpan<float2> uv_map_eval = mesh_eval.attribute_get_for_read<float2>( - uv_map_name, ATTR_DOMAIN_CORNER, {0.0f, 0.0f}); - const VArraySpan<float3> rest_positions = mesh_eval.attribute_get_for_read<float3>( - rest_position_name, ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f}); + const VArraySpan<float2> uv_map_orig = mesh_attributes_orig.lookup<float2>(uv_map_name, + ATTR_DOMAIN_CORNER); + const VArraySpan<float2> uv_map_eval = mesh_attributes_eval.lookup<float2>(uv_map_name, + ATTR_DOMAIN_CORNER); + const VArraySpan<float3> rest_positions = mesh_attributes_eval.lookup<float3>(rest_position_name, + ATTR_DOMAIN_POINT); const Span<float2> surface_uv_coords = curves.surface_uv_coords(); const Span<MLoopTri> looptris_orig{BKE_mesh_runtime_looptri_ensure(surface_mesh_orig), diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 68489d1b9a6..408596b65aa 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -49,7 +49,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes { for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); + GAttributeReader attribute = in_component.attributes()->lookup(attribute_id); if (!attribute) { continue; } @@ -60,8 +60,9 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes } const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( - attribute_id, attribute.domain, data_type); + GSpanAttributeWriter result_attribute = + result_component.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, attribute.domain, data_type); if (!result_attribute) { continue; @@ -70,10 +71,10 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); VArraySpan<T> span{attribute.varray.typed<T>()}; - MutableSpan<T> out_span = result_attribute.as_span<T>(); + MutableSpan<T> out_span = result_attribute.span.typed<T>(); out_span.copy_from(span); }); - result_attribute.save(); + result_attribute.finish(); } } @@ -89,7 +90,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin { for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); + GAttributeReader attribute = in_component.attributes()->lookup(attribute_id); if (!attribute) { continue; } @@ -100,8 +101,9 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin } const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( - attribute_id, attribute.domain, data_type); + GSpanAttributeWriter result_attribute = + result_component.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, attribute.domain, data_type); if (!result_attribute) { continue; @@ -110,10 +112,10 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); VArraySpan<T> span{attribute.varray.typed<T>()}; - MutableSpan<T> out_span = result_attribute.as_span<T>(); + MutableSpan<T> out_span = result_attribute.span.typed<T>(); copy_data_based_on_mask(span, out_span, mask); }); - result_attribute.save(); + result_attribute.finish(); } } @@ -125,7 +127,7 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind { for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); + GAttributeReader attribute = in_component.attributes()->lookup(attribute_id); if (!attribute) { continue; } @@ -136,8 +138,9 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind } const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( - attribute_id, attribute.domain, data_type); + GSpanAttributeWriter result_attribute = + result_component.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, attribute.domain, data_type); if (!result_attribute) { continue; @@ -146,10 +149,10 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); VArraySpan<T> span{attribute.varray.typed<T>()}; - MutableSpan<T> out_span = result_attribute.as_span<T>(); + MutableSpan<T> out_span = result_attribute.span.typed<T>(); copy_data_based_on_map(span, out_span, index_map); }); - result_attribute.save(); + result_attribute.finish(); } } @@ -319,7 +322,7 @@ static void delete_curves_selection(GeometrySet &geometry_set, const CurveComponent &src_component = *geometry_set.get_component_for_read<CurveComponent>(); GeometryComponentFieldContext field_context{src_component, selection_domain}; - const int domain_num = src_component.attribute_domain_num(selection_domain); + const int domain_num = src_component.attribute_domain_size(selection_domain); fn::FieldEvaluator evaluator{field_context, domain_num}; evaluator.set_selection(selection_field); evaluator.evaluate(); @@ -351,7 +354,7 @@ static void separate_point_cloud_selection(GeometrySet &geometry_set, *geometry_set.get_component_for_read<PointCloudComponent>(); GeometryComponentFieldContext field_context{src_points, ATTR_DOMAIN_POINT}; - fn::FieldEvaluator evaluator{field_context, src_points.attribute_domain_num(ATTR_DOMAIN_POINT)}; + fn::FieldEvaluator evaluator{field_context, src_points.attribute_domain_size(ATTR_DOMAIN_POINT)}; evaluator.set_selection(selection_field); evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); @@ -379,8 +382,7 @@ static void delete_selected_instances(GeometrySet &geometry_set, InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>(); GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE}; - fn::FieldEvaluator evaluator{field_context, - instances.attribute_domain_num(ATTR_DOMAIN_INSTANCE)}; + fn::FieldEvaluator evaluator{field_context, instances.instances_num()}; evaluator.set_selection(selection_field); evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); @@ -1058,7 +1060,7 @@ static void separate_mesh_selection(GeometrySet &geometry_set, GeometryComponentFieldContext field_context{src_component, selection_domain}; fn::FieldEvaluator evaluator{field_context, - src_component.attribute_domain_num(selection_domain)}; + src_component.attribute_domain_size(selection_domain)}; evaluator.add(selection_field); evaluator.evaluate(); const VArray<bool> selection = evaluator.get_evaluated<bool>(0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index f95601813a3..faf5b7f65fa 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -290,31 +290,32 @@ BLI_NOINLINE static void propagate_existing_attributes( const Span<int> looptri_indices) { const Mesh &mesh = *mesh_component.get_for_read(); + const AttributeAccessor mesh_attributes = *mesh_component.attributes(); + MutableAttributeAccessor point_attributes = *point_component.attributes_for_write(); for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; const eCustomDataType output_data_type = entry.value.data_type; - ReadAttributeLookup source_attribute = mesh_component.attribute_try_get_for_read(attribute_id); + GAttributeReader source_attribute = mesh_attributes.lookup(attribute_id); if (!source_attribute) { continue; } /* The output domain is always #ATTR_DOMAIN_POINT, since we are creating a point cloud. */ - OutputAttribute attribute_out = point_component.attribute_try_get_for_output_only( + GSpanAttributeWriter attribute_out = point_attributes.lookup_or_add_for_write_only_span( attribute_id, ATTR_DOMAIN_POINT, output_data_type); if (!attribute_out) { continue; } - GMutableSpan out_span = attribute_out.as_span(); interpolate_attribute(mesh, bary_coords, looptri_indices, source_attribute.domain, source_attribute.varray, - out_span); - attribute_out.save(); + attribute_out.span); + attribute_out.finish(); } } @@ -331,25 +332,21 @@ BLI_NOINLINE static void compute_attribute_outputs(const MeshComponent &mesh_com const Span<int> looptri_indices, const AttributeOutputs &attribute_outputs) { - OutputAttribute_Typed<int> id_attribute = point_component.attribute_try_get_for_output_only<int>( - "id", ATTR_DOMAIN_POINT); - MutableSpan<int> ids = id_attribute.as_span(); + MutableAttributeAccessor pointcloud_attributes = *point_component.attributes_for_write(); - OutputAttribute_Typed<float3> normal_attribute; - OutputAttribute_Typed<float3> rotation_attribute; + SpanAttributeWriter<int> ids = pointcloud_attributes.lookup_or_add_for_write_only_span<int>( + "id", ATTR_DOMAIN_POINT); - MutableSpan<float3> normals; - MutableSpan<float3> rotations; + SpanAttributeWriter<float3> normals; + SpanAttributeWriter<float3> rotations; if (attribute_outputs.normal_id) { - normal_attribute = point_component.attribute_try_get_for_output_only<float3>( + normals = pointcloud_attributes.lookup_or_add_for_write_only_span<float3>( attribute_outputs.normal_id.get(), ATTR_DOMAIN_POINT); - normals = normal_attribute.as_span(); } if (attribute_outputs.rotation_id) { - rotation_attribute = point_component.attribute_try_get_for_output_only<float3>( + rotations = pointcloud_attributes.lookup_or_add_for_write_only_span<float3>( attribute_outputs.rotation_id.get(), ATTR_DOMAIN_POINT); - rotations = rotation_attribute.as_span(); } const Mesh &mesh = *mesh_component.get_for_read(); @@ -368,27 +365,27 @@ BLI_NOINLINE static void compute_attribute_outputs(const MeshComponent &mesh_com const float3 v1_pos = float3(mesh.mvert[v1_index].co); const float3 v2_pos = float3(mesh.mvert[v2_index].co); - ids[i] = noise::hash(noise::hash_float(bary_coord), looptri_index); + ids.span[i] = noise::hash(noise::hash_float(bary_coord), looptri_index); float3 normal; - if (!normals.is_empty() || !rotations.is_empty()) { + if (!normals.span.is_empty() || !rotations.span.is_empty()) { normal_tri_v3(normal, v0_pos, v1_pos, v2_pos); } - if (!normals.is_empty()) { - normals[i] = normal; + if (!normals.span.is_empty()) { + normals.span[i] = normal; } - if (!rotations.is_empty()) { - rotations[i] = normal_to_euler_rotation(normal); + if (!rotations.span.is_empty()) { + rotations.span[i] = normal_to_euler_rotation(normal); } } - id_attribute.save(); + ids.finish(); - if (normal_attribute) { - normal_attribute.save(); + if (normals) { + normals.finish(); } - if (rotation_attribute) { - rotation_attribute.save(); + if (rotations) { + rotations.finish(); } } @@ -398,11 +395,11 @@ static Array<float> calc_full_density_factors_with_selection(const MeshComponent { const eAttrDomain attribute_domain = ATTR_DOMAIN_CORNER; GeometryComponentFieldContext field_context{component, attribute_domain}; - const int domain_num = component.attribute_domain_num(attribute_domain); + const int domain_size = component.attribute_domain_size(attribute_domain); - Array<float> densities(domain_num, 0.0f); + Array<float> densities(domain_size, 0.0f); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); evaluator.add_with_destination(density_field, densities.as_mutable_span()); evaluator.evaluate(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 8a256a9b91b..bf5479d552e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -146,9 +146,12 @@ static void transfer_attributes( const GeometryComponent &src_component, GeometryComponent &dst_component) { + const AttributeAccessor src_attributes = *src_component.attributes(); + MutableAttributeAccessor dst_attributes = *dst_component.attributes_for_write(); + for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id); + GAttributeReader src_attribute = src_attributes.lookup(attribute_id); if (!src_attribute) { continue; } @@ -166,7 +169,7 @@ static void transfer_attributes( } const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( src_attribute.varray.type()); - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( + GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( attribute_id, out_domain, data_type); if (!dst_attribute) { @@ -176,7 +179,7 @@ static void transfer_attributes( attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); VArraySpan<T> span{src_attribute.varray.typed<T>()}; - MutableSpan<T> dst_span = dst_attribute.as_span<T>(); + MutableSpan<T> dst_span = dst_attribute.span.typed<T>(); if (src_attribute.domain == ATTR_DOMAIN_FACE) { dst_span.take_front(span.size()).copy_from(span); if (keep_boundaries) { @@ -193,7 +196,7 @@ static void transfer_attributes( copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_face_corners_map); } }); - dst_attribute.save(); + dst_attribute.finish(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 5fe300e0a08..41136060ab7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -147,17 +147,17 @@ static void create_duplicate_index_attribute(GeometryComponent &component, const IndexAttributes &attribute_outputs, const Span<int> offsets) { - OutputAttribute_Typed<int> copy_attribute = component.attribute_try_get_for_output_only<int>( - attribute_outputs.duplicate_index.get(), output_domain); - MutableSpan<int> duplicate_indices = copy_attribute.as_span(); + SpanAttributeWriter<int> duplicate_indices = + component.attributes_for_write()->lookup_or_add_for_write_only_span<int>( + attribute_outputs.duplicate_index.get(), output_domain); for (const int i : IndexRange(selection.size())) { const IndexRange range = range_for_offsets_index(offsets, i); - MutableSpan<int> indices = duplicate_indices.slice(range); + MutableSpan<int> indices = duplicate_indices.span.slice(range); for (const int i : indices.index_range()) { indices[i] = i; } } - copy_attribute.save(); + duplicate_indices.finish(); } /** @@ -168,20 +168,21 @@ static void copy_stable_id_point(const Span<int> offsets, const GeometryComponent &src_component, GeometryComponent &dst_component) { - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read("id"); + GAttributeReader src_attribute = src_component.attributes()->lookup("id"); if (!src_attribute) { return; } - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); + GSpanAttributeWriter dst_attribute = + dst_component.attributes_for_write()->lookup_or_add_for_write_only_span( + "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); if (!dst_attribute) { return; } VArraySpan<int> src{src_attribute.varray.typed<int>()}; - MutableSpan<int> dst = dst_attribute.as_span<int>(); + MutableSpan<int> dst = dst_attribute.span.typed<int>(); threaded_id_offset_copy(offsets, src, dst); - dst_attribute.save(); + dst_attribute.finish(); } static void copy_attributes_without_id(GeometrySet &geometry_set, @@ -197,25 +198,26 @@ static void copy_attributes_without_id(GeometrySet &geometry_set, for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id); + GAttributeReader src_attribute = src_component.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()); - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - attribute_id, out_domain, data_type); + GSpanAttributeWriter dst_attribute = + dst_component.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); VArraySpan<T> src = src_attribute.varray.typed<T>(); - MutableSpan<T> dst = dst_attribute.as_span<T>(); + MutableSpan<T> dst = dst_attribute.span.typed<T>(); threaded_slice_fill<T>(offsets, selection, src, dst); }); - dst_attribute.save(); + dst_attribute.finish(); } } @@ -242,7 +244,7 @@ static void copy_curve_attributes_without_id(const GeometrySet &geometry_set, for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id); + GAttributeReader src_attribute = src_component.attributes()->lookup(attribute_id); if (!src_attribute) { continue; } @@ -250,8 +252,9 @@ static void copy_curve_attributes_without_id(const GeometrySet &geometry_set, eAttrDomain out_domain = src_attribute.domain; const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( src_attribute.varray.type()); - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - attribute_id, out_domain, data_type); + GSpanAttributeWriter dst_attribute = + dst_component.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, out_domain, data_type); if (!dst_attribute) { continue; } @@ -259,7 +262,7 @@ static void copy_curve_attributes_without_id(const GeometrySet &geometry_set, attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); VArraySpan<T> src{src_attribute.varray.typed<T>()}; - MutableSpan<T> dst = dst_attribute.as_span<T>(); + MutableSpan<T> dst = dst_attribute.span.typed<T>(); switch (out_domain) { case ATTR_DOMAIN_CURVE: @@ -280,7 +283,7 @@ static void copy_curve_attributes_without_id(const GeometrySet &geometry_set, break; } }); - dst_attribute.save(); + dst_attribute.finish(); } } @@ -297,18 +300,19 @@ static void copy_stable_id_curves(const bke::CurvesGeometry &src_curves, bke::CurvesGeometry &dst_curves, CurveComponent &dst_component) { - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read("id"); + GAttributeReader src_attribute = src_component.attributes()->lookup("id"); if (!src_attribute) { return; } - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); + GSpanAttributeWriter dst_attribute = + dst_component.attributes_for_write()->lookup_or_add_for_write_only_span( + "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); if (!dst_attribute) { return; } VArraySpan<int> src{src_attribute.varray.typed<int>()}; - MutableSpan<int> dst = dst_attribute.as_span<int>(); + MutableSpan<int> dst = dst_attribute.span.typed<int>(); threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) { for (const int i_selection : range) { @@ -322,7 +326,7 @@ static void copy_stable_id_curves(const bke::CurvesGeometry &src_curves, } } }); - dst_attribute.save(); + dst_attribute.finish(); } static void duplicate_curves(GeometrySet &geometry_set, @@ -423,7 +427,7 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set, for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id); + GAttributeReader src_attribute = src_component.attributes()->lookup(attribute_id); if (!src_attribute) { continue; } @@ -431,8 +435,9 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set, eAttrDomain out_domain = src_attribute.domain; const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( src_attribute.varray.type()); - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - attribute_id, out_domain, data_type); + GSpanAttributeWriter dst_attribute = + dst_component.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, out_domain, data_type); if (!dst_attribute) { continue; } @@ -440,7 +445,7 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set, attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); VArraySpan<T> src{src_attribute.varray.typed<T>()}; - MutableSpan<T> dst = dst_attribute.as_span<T>(); + MutableSpan<T> dst = dst_attribute.span.typed<T>(); switch (out_domain) { case ATTR_DOMAIN_FACE: @@ -459,7 +464,7 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set, break; } }); - dst_attribute.save(); + dst_attribute.finish(); } } @@ -477,18 +482,19 @@ static void copy_stable_id_faces(const Mesh &mesh, const MeshComponent &src_component, MeshComponent &dst_component) { - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read("id"); + GAttributeReader src_attribute = src_component.attributes()->lookup("id"); if (!src_attribute) { return; } - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); + GSpanAttributeWriter dst_attribute = + dst_component.attributes_for_write()->lookup_or_add_for_write_only_span( + "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); if (!dst_attribute) { return; } VArraySpan<int> src{src_attribute.varray.typed<int>()}; - MutableSpan<int> dst = dst_attribute.as_span<int>(); + MutableSpan<int> dst = dst_attribute.span.typed<int>(); Span<MPoly> polys(mesh.mpoly, mesh.totpoly); int loop_index = 0; @@ -511,7 +517,7 @@ static void copy_stable_id_faces(const Mesh &mesh, } } - dst_attribute.save(); + dst_attribute.finish(); } static void duplicate_faces(GeometrySet &geometry_set, @@ -636,7 +642,7 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set, for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id); + GAttributeReader src_attribute = src_component.attributes()->lookup(attribute_id); if (!src_attribute) { continue; } @@ -644,15 +650,16 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set, const eAttrDomain out_domain = src_attribute.domain; const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( src_attribute.varray.type()); - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - attribute_id, out_domain, data_type); + GSpanAttributeWriter dst_attribute = + dst_component.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); VArraySpan<T> src{src_attribute.varray.typed<T>()}; - MutableSpan<T> dst = dst_attribute.as_span<T>(); + MutableSpan<T> dst = dst_attribute.span.typed<T>(); switch (out_domain) { case ATTR_DOMAIN_EDGE: @@ -665,7 +672,7 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set, break; } }); - dst_attribute.save(); + dst_attribute.finish(); } } @@ -679,12 +686,13 @@ static void copy_stable_id_edges(const Mesh &mesh, const MeshComponent &src_component, MeshComponent &dst_component) { - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read("id"); + GAttributeReader src_attribute = src_component.attributes()->lookup("id"); if (!src_attribute) { return; } - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); + GSpanAttributeWriter dst_attribute = + dst_component.attributes_for_write()->lookup_or_add_for_write_only_span( + "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); if (!dst_attribute) { return; } @@ -692,7 +700,7 @@ static void copy_stable_id_edges(const Mesh &mesh, Span<MEdge> edges(mesh.medge, mesh.totedge); VArraySpan<int> src{src_attribute.varray.typed<int>()}; - MutableSpan<int> dst = dst_attribute.as_span<int>(); + MutableSpan<int> dst = dst_attribute.span.typed<int>(); threading::parallel_for(IndexRange(selection.size()), 1024, [&](IndexRange range) { for (const int i_selection : range) { const IndexRange edge_range = range_for_offsets_index(edge_offsets, i_selection); @@ -710,7 +718,7 @@ static void copy_stable_id_edges(const Mesh &mesh, } } }); - dst_attribute.save(); + dst_attribute.finish(); } static void duplicate_edges(GeometrySet &geometry_set, @@ -837,7 +845,7 @@ static void duplicate_points_curve(GeometrySet &geometry_set, for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup src_attribute = src_component.attribute_try_get_for_read(attribute_id); + GAttributeReader src_attribute = src_component.attributes()->lookup(attribute_id); if (!src_attribute) { continue; } @@ -845,8 +853,9 @@ static void duplicate_points_curve(GeometrySet &geometry_set, eAttrDomain domain = src_attribute.domain; const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( src_attribute.varray.type()); - OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - attribute_id, domain, data_type); + GSpanAttributeWriter dst_attribute = + dst_component.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, domain, data_type); if (!dst_attribute) { continue; } @@ -854,7 +863,7 @@ static void duplicate_points_curve(GeometrySet &geometry_set, attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); VArraySpan<T> src{src_attribute.varray.typed<T>()}; - MutableSpan<T> dst = dst_attribute.as_span<T>(); + MutableSpan<T> dst = dst_attribute.span.typed<T>(); switch (domain) { case ATTR_DOMAIN_CURVE: @@ -873,7 +882,7 @@ static void duplicate_points_curve(GeometrySet &geometry_set, break; } }); - dst_attribute.save(); + dst_attribute.finish(); } copy_stable_id_point(offsets, src_component, dst_component); @@ -949,7 +958,7 @@ static void duplicate_points_pointcloud(GeometrySet &geometry_set, { const PointCloudComponent &src_points = *geometry_set.get_component_for_read<PointCloudComponent>(); - const int point_num = src_points.attribute_domain_num(ATTR_DOMAIN_POINT); + const int point_num = src_points.attribute_domain_size(ATTR_DOMAIN_POINT); GeometryComponentFieldContext field_context{src_points, ATTR_DOMAIN_POINT}; FieldEvaluator evaluator{field_context, point_num}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc b/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc index 94fbec66bfe..84acab47661 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_edge_split.cc @@ -57,8 +57,8 @@ static void node_geo_exec(GeoNodeExecParams params) const MeshComponent &mesh_component = *geometry_set.get_component_for_read<MeshComponent>(); GeometryComponentFieldContext field_context{mesh_component, ATTR_DOMAIN_EDGE}; - const int domain_num = mesh_component.attribute_domain_num(ATTR_DOMAIN_EDGE); - fn::FieldEvaluator selection_evaluator{field_context, domain_num}; + const int domain_size = mesh_component.attribute_domain_size(ATTR_DOMAIN_EDGE); + fn::FieldEvaluator selection_evaluator{field_context, domain_size}; selection_evaluator.add(selection_field); selection_evaluator.evaluate(); const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 59d7154db6e..baa9952b950 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -66,21 +66,21 @@ static void save_selection_as_attribute(MeshComponent &component, const eAttrDomain domain, const IndexMask selection) { - BLI_assert(!component.attribute_exists(id)); + BLI_assert(!component.attributes()->contains(id)); - OutputAttribute_Typed<bool> attribute = component.attribute_try_get_for_output_only<bool>( - id, domain); + SpanAttributeWriter<bool> attribute = + component.attributes_for_write()->lookup_or_add_for_write_span<bool>(id, domain); /* Rely on the new attribute being zeroed by default. */ - BLI_assert(!attribute.as_span().as_span().contains(true)); + BLI_assert(!attribute.span.as_span().contains(true)); if (selection.is_range()) { - attribute.as_span().slice(selection.as_range()).fill(true); + attribute.span.slice(selection.as_range()).fill(true); } else { - attribute.as_span().fill_indices(selection, true); + attribute.span.fill_indices(selection, true); } - attribute.save(); + attribute.finish(); } static MutableSpan<MVert> mesh_verts(Mesh &mesh) @@ -168,7 +168,7 @@ static MutableSpan<int> get_orig_index_layer(Mesh &mesh, const eAttrDomain domai component.replace(&mesh, GeometryOwnershipType::ReadOnly); CustomData &custom_data = get_customdata(mesh, domain); if (int *orig_indices = static_cast<int *>(CustomData_get_layer(&custom_data, CD_ORIGINDEX))) { - return {orig_indices, component.attribute_domain_num(domain)}; + return {orig_indices, component.attribute_domain_size(domain)}; } return {}; } @@ -280,16 +280,18 @@ static void extrude_mesh_vertices(MeshComponent &component, new_edges[i_selection] = new_loose_edge(selection[i_selection], new_vert_range[i_selection]); } - component.attribute_foreach([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + MutableAttributeAccessor attributes = *component.attributes_for_write(); + + attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { if (!ELEM(meta_data.domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE)) { return true; } - OutputAttribute attribute = component.attribute_try_get_for_output( + GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); - MutableSpan<T> data = attribute.as_span().typed<T>(); - switch (attribute.domain()) { + MutableSpan<T> data = attribute.span.typed<T>(); + switch (attribute.domain) { case ATTR_DOMAIN_POINT: { /* New vertices copy the attribute values from their source vertex. */ copy_with_mask(data.slice(new_vert_range), data.as_span(), selection); @@ -307,7 +309,7 @@ static void extrude_mesh_vertices(MeshComponent &component, } }); - attribute.save(); + attribute.finish(); return true; }); @@ -524,8 +526,10 @@ static void extrude_mesh_edges(MeshComponent &component, const Array<Vector<int>> new_vert_to_duplicate_edge_map = create_vert_to_edge_map( new_vert_range.size(), duplicate_edges, orig_vert_size); - component.attribute_foreach([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { - OutputAttribute attribute = component.attribute_try_get_for_output( + MutableAttributeAccessor attributes = *component.attributes_for_write(); + + attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); if (!attribute) { return true; /* Impossible to write the "normal" attribute. */ @@ -533,8 +537,8 @@ static void extrude_mesh_edges(MeshComponent &component, attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); - MutableSpan<T> data = attribute.as_span().typed<T>(); - switch (attribute.domain()) { + MutableSpan<T> data = attribute.span.typed<T>(); + switch (attribute.domain) { case ATTR_DOMAIN_POINT: { /* New vertices copy the attribute values from their source vertex. */ copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices); @@ -626,7 +630,7 @@ static void extrude_mesh_edges(MeshComponent &component, } }); - attribute.save(); + attribute.finish(); return true; }); @@ -902,8 +906,10 @@ static void extrude_mesh_face_regions(MeshComponent &component, const Array<Vector<int>> new_vert_to_duplicate_edge_map = create_vert_to_edge_map( new_vert_range.size(), boundary_edges, orig_vert_size); - component.attribute_foreach([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { - OutputAttribute attribute = component.attribute_try_get_for_output( + MutableAttributeAccessor attributes = *component.attributes_for_write(); + + attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); if (!attribute) { return true; /* Impossible to write the "normal" attribute. */ @@ -911,8 +917,8 @@ static void extrude_mesh_face_regions(MeshComponent &component, attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); - MutableSpan<T> data = attribute.as_span().typed<T>(); - switch (attribute.domain()) { + MutableSpan<T> data = attribute.span.typed<T>(); + switch (attribute.domain) { case ATTR_DOMAIN_POINT: { /* New vertices copy the attributes from their original vertices. */ copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices); @@ -991,7 +997,7 @@ static void extrude_mesh_face_regions(MeshComponent &component, } }); - attribute.save(); + attribute.finish(); return true; }); @@ -1154,8 +1160,10 @@ static void extrude_individual_mesh_faces(MeshComponent &component, } }); - component.attribute_foreach([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { - OutputAttribute attribute = component.attribute_try_get_for_output( + MutableAttributeAccessor attributes = *component.attributes_for_write(); + + attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { + GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); if (!attribute) { return true; /* Impossible to write the "normal" attribute. */ @@ -1163,8 +1171,8 @@ static void extrude_individual_mesh_faces(MeshComponent &component, attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); - MutableSpan<T> data = attribute.as_span().typed<T>(); - switch (attribute.domain()) { + MutableSpan<T> data = attribute.span.typed<T>(); + switch (attribute.domain) { case ATTR_DOMAIN_POINT: { /* New vertices copy the attributes from their original vertices. */ MutableSpan<T> new_data = data.slice(new_vert_range); @@ -1267,7 +1275,7 @@ static void extrude_individual_mesh_faces(MeshComponent &component, } }); - attribute.save(); + attribute.finish(); return true; }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_field_at_index.cc b/source/blender/nodes/geometry/nodes/node_geo_field_at_index.cc index 7839e148ee3..64861e529bc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_field_at_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_field_at_index.cc @@ -91,7 +91,7 @@ class FieldAtIndex final : public GeometryFieldInput { { const GeometryComponentFieldContext value_field_context{component, value_field_domain_}; FieldEvaluator value_evaluator{value_field_context, - component.attribute_domain_num(value_field_domain_)}; + component.attribute_domain_size(value_field_domain_)}; value_evaluator.add(value_field_); value_evaluator.evaluate(); const GVArray &values = value_evaluator.get_evaluated(0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_field_on_domain.cc b/source/blender/nodes/geometry/nodes/node_geo_field_on_domain.cc index e6906f4fb21..5939ed5334d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_field_on_domain.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_field_on_domain.cc @@ -85,12 +85,12 @@ class FieldOnDomain final : public GeometryFieldInput { IndexMask /* mask */) const final { const GeometryComponentFieldContext context{component, src_domain_}; - FieldEvaluator value_evaluator{context, component.attribute_domain_num(src_domain_)}; + FieldEvaluator value_evaluator{context, component.attribute_domain_size(src_domain_)}; value_evaluator.add(src_field_); value_evaluator.evaluate(); const GVArray &values = value_evaluator.get_evaluated(0); - return component.attribute_try_adapt_domain(values, src_domain_, domain); + return component.attributes()->adapt_domain(values, src_domain_, domain); } }; diff --git a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc index 0484017cf3b..15b2822805a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc @@ -22,11 +22,11 @@ static void node_declare(NodeDeclarationBuilder &b) static void mesh_flip_faces(MeshComponent &component, const Field<bool> &selection_field) { GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_FACE}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_FACE); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_FACE); + if (domain_size == 0) { return; } - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.add(selection_field); evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_as_mask(0); @@ -49,20 +49,21 @@ static void mesh_flip_faces(MeshComponent &component, const Field<bool> &selecti } } - component.attribute_foreach( + MutableAttributeAccessor attributes = *component.attributes_for_write(); + attributes.for_all( [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { if (meta_data.domain == ATTR_DOMAIN_CORNER) { - OutputAttribute attribute = component.attribute_try_get_for_output( - attribute_id, ATTR_DOMAIN_CORNER, meta_data.data_type, nullptr); + GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( + attribute_id, ATTR_DOMAIN_CORNER, meta_data.data_type); attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); - MutableSpan<T> dst_span = attribute.as_span<T>(); + MutableSpan<T> dst_span = attribute.span.typed<T>(); for (const int j : selection.index_range()) { const MPoly &poly = polys[selection[j]]; dst_span.slice(poly.loopstart + 1, poly.totloop - 1).reverse(); } }); - attribute.save(); + attribute.finish(); } return true; }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc index e0aaf43235c..bc1b9e940a1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_curve_handles.cc @@ -39,11 +39,13 @@ class HandlePositionFieldInput final : public GeometryFieldInput { evaluator.evaluate(); const VArray<bool> relative = evaluator.get_evaluated<bool>(0); - VArray<float3> positions = component.attribute_get_for_read<float3>( + const AttributeAccessor attributes = *component.attributes(); + + VArray<float3> positions = attributes.lookup_or_default<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); StringRef side = left_ ? "handle_left" : "handle_right"; - VArray<float3> handles = component.attribute_get_for_read<float3>( + VArray<float3> handles = attributes.lookup_or_default<float3>( side, ATTR_DOMAIN_POINT, {0, 0, 0}); if (relative.is_single()) { @@ -52,10 +54,10 @@ class HandlePositionFieldInput final : public GeometryFieldInput { for (const int i : positions.index_range()) { output[i] = handles[i] - positions[i]; } - return component.attribute_try_adapt_domain<float3>( + return attributes.adapt_domain<float3>( VArray<float3>::ForContainer(std::move(output)), ATTR_DOMAIN_POINT, domain); } - return component.attribute_try_adapt_domain<float3>(handles, ATTR_DOMAIN_POINT, domain); + return attributes.adapt_domain<float3>(handles, ATTR_DOMAIN_POINT, domain); } Array<float3> output(positions.size()); @@ -67,7 +69,7 @@ class HandlePositionFieldInput final : public GeometryFieldInput { output[i] = handles[i]; } } - return component.attribute_try_adapt_domain<float3>( + return component.attributes()->adapt_domain<float3>( VArray<float3>::ForContainer(std::move(output)), ATTR_DOMAIN_POINT, domain); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc index f27e0305c7d..b009aaa5291 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc @@ -91,7 +91,7 @@ class AngleFieldInput final : public GeometryFieldInput { }; VArray<float> angles = VArray<float>::ForFunc(mesh->totedge, angle_fn); - return component.attribute_try_adapt_domain<float>( + return component.attributes()->adapt_domain<float>( std::move(angles), ATTR_DOMAIN_EDGE, domain); } @@ -166,7 +166,7 @@ class SignedAngleFieldInput final : public GeometryFieldInput { }; VArray<float> angles = VArray<float>::ForFunc(mesh->totedge, angle_fn); - return component.attribute_try_adapt_domain<float>( + return component.attributes()->adapt_domain<float>( std::move(angles), ATTR_DOMAIN_EDGE, domain); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc index cbc2ebc3e68..50d6998bb27 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc @@ -40,7 +40,7 @@ class EdgeNeighborCountFieldInput final : public GeometryFieldInput { face_count[mesh->mloop[i].e]++; } - return mesh_component.attribute_try_adapt_domain<int>( + return mesh_component.attributes()->adapt_domain<int>( VArray<int>::ForContainer(std::move(face_count)), ATTR_DOMAIN_EDGE, domain); } return {}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_vertices.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_vertices.cc index 6201ad26bfb..83e511f45c2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_vertices.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_vertices.cc @@ -93,14 +93,14 @@ static VArray<float3> construct_edge_positions_gvarray(const MeshComponent &comp } if (vertex == VERTEX_ONE) { - return component.attribute_try_adapt_domain<float3>( + return component.attributes()->adapt_domain<float3>( VArray<float3>::ForFunc( mesh->totedge, [mesh](const int i) { return float3(mesh->mvert[mesh->medge[i].v1].co); }), ATTR_DOMAIN_EDGE, domain); } - return component.attribute_try_adapt_domain<float3>( + return component.attributes()->adapt_domain<float3>( VArray<float3>::ForFunc( mesh->totedge, [mesh](const int i) { return float3(mesh->mvert[mesh->medge[i].v2].co); }), diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc index 7a0e3e37a65..4d21bf9443a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_area.cc @@ -29,7 +29,7 @@ static VArray<float> construct_face_area_gvarray(const MeshComponent &component, return BKE_mesh_calc_poly_area(mp, &mesh->mloop[mp->loopstart], mesh->mvert); }; - return component.attribute_try_adapt_domain<float>( + return component.attributes()->adapt_domain<float>( VArray<float>::ForFunc(mesh->totpoly, area_fn), ATTR_DOMAIN_FACE, domain); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc index d02f7291704..6b04ff08d9e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_is_planar.cc @@ -80,7 +80,7 @@ class PlanarFieldInput final : public GeometryFieldInput { return max - min < thresholds[i_poly] / 2.0f; }; - return component.attribute_try_adapt_domain<bool>( + return component.attributes()->adapt_domain<bool>( VArray<bool>::ForFunc(mesh->totpoly, planar_fn), ATTR_DOMAIN_FACE, domain); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc index 67a21cb06f0..a225ce61b14 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_face_neighbors.cc @@ -40,7 +40,7 @@ static VArray<int> construct_neighbor_count_gvarray(const MeshComponent &compone } } - return component.attribute_try_adapt_domain<int>( + return component.attributes()->adapt_domain<int>( VArray<int>::ForContainer(std::move(poly_count)), ATTR_DOMAIN_FACE, domain); } @@ -83,7 +83,7 @@ static VArray<int> construct_vertex_count_gvarray(const MeshComponent &component return {}; } - return component.attribute_try_adapt_domain<int>( + return component.attributes()->adapt_domain<int>( VArray<int>::ForFunc(mesh->totpoly, [mesh](const int i) -> float { return mesh->mpoly[i].totloop; }), ATTR_DOMAIN_FACE, diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc index bd57924d685..2c7eef5665f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc @@ -54,7 +54,7 @@ class IslandFieldInput final : public GeometryFieldInput { output[i] = ordered_roots.index_of_or_add(root); } - return mesh_component.attribute_try_adapt_domain<int>( + return mesh_component.attributes()->adapt_domain<int>( VArray<int>::ForContainer(std::move(output)), ATTR_DOMAIN_POINT, domain); } @@ -101,7 +101,8 @@ class IslandCountFieldInput final : public GeometryFieldInput { island_list.add(root); } - return VArray<int>::ForSingle(island_list.size(), mesh_component.attribute_domain_num(domain)); + return VArray<int>::ForSingle(island_list.size(), + mesh_component.attribute_domain_size(domain)); } uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc index def82eefca5..267ba44cc00 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc @@ -32,7 +32,7 @@ static VArray<int> construct_curve_point_count_gvarray(const CurveComponent &com } if (domain == ATTR_DOMAIN_POINT) { VArray<int> count = VArray<int>::ForFunc(curves.curves_num(), count_fn); - return component.attribute_try_adapt_domain<int>( + return component.attributes()->adapt_domain<int>( std::move(count), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc index f5831941094..a2aab5464aa 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc @@ -75,7 +75,7 @@ static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &comp const VArray<int8_t> types = curves.curve_types(); if (curves.is_single_type(CURVE_TYPE_POLY)) { - return component.attribute_try_adapt_domain<float3>( + return component.attributes()->adapt_domain<float3>( VArray<float3>::ForSpan(curves.evaluated_tangents()), ATTR_DOMAIN_POINT, domain); } @@ -86,7 +86,7 @@ static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &comp } if (domain == ATTR_DOMAIN_CURVE) { - return component.attribute_try_adapt_domain<float3>( + return component.attributes()->adapt_domain<float3>( VArray<float3>::ForContainer(std::move(tangents)), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index 21ef8765e43..3ce26a086e2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -50,7 +50,7 @@ static void add_instances_from_component( const Map<AttributeIDRef, AttributeKind> &attributes_to_propagate) { const eAttrDomain domain = ATTR_DOMAIN_POINT; - const int domain_num = src_component.attribute_domain_num(domain); + const int domain_num = src_component.attribute_domain_size(domain); VArray<bool> pick_instance; VArray<int> indices; @@ -82,7 +82,7 @@ static void add_instances_from_component( MutableSpan<float4x4> dst_transforms = dst_component.instance_transforms().slice(start_len, select_len); - VArray<float3> positions = src_component.attribute_get_for_read<float3>( + VArray<float3> positions = src_component.attributes()->lookup_or_default<float3>( "position", domain, {0, 0, 0}); const InstancesComponent *src_instances = instance.get_component_for_read<InstancesComponent>(); @@ -154,12 +154,12 @@ static void add_instances_from_component( } } - bke::CustomDataAttributes &instance_attributes = dst_component.attributes(); + bke::CustomDataAttributes &instance_attributes = dst_component.instance_attributes(); for (const auto item : attributes_to_propagate.items()) { const AttributeIDRef &attribute_id = item.key; const AttributeKind attribute_kind = item.value; - const GVArray src_attribute = src_component.attribute_get_for_read( + const GVArray src_attribute = src_component.attributes()->lookup_or_default( attribute_id, ATTR_DOMAIN_POINT, attribute_kind.data_type); BLI_assert(src_attribute); std::optional<GMutableSpan> dst_attribute_opt = instance_attributes.get_for_write( diff --git a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc index ffc6137cf83..edbe6e1593f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc @@ -40,9 +40,9 @@ static void convert_instances_to_points(GeometrySet &geometry_set, const InstancesComponent &instances = *geometry_set.get_component_for_read<InstancesComponent>(); GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE}; - const int domain_num = instances.attribute_domain_num(ATTR_DOMAIN_INSTANCE); + const int domain_size = instances.instances_num(); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(std::move(selection_field)); evaluator.add(std::move(position_field)); evaluator.add(std::move(radius_field)); @@ -75,18 +75,18 @@ static void convert_instances_to_points(GeometrySet &geometry_set, const AttributeIDRef &attribute_id = item.key; const AttributeKind attribute_kind = item.value; - const GVArray src = instances.attribute_get_for_read( + const GVArray src = instances.attributes()->lookup_or_default( attribute_id, ATTR_DOMAIN_INSTANCE, attribute_kind.data_type); BLI_assert(src); - OutputAttribute dst = points.attribute_try_get_for_output_only( + GSpanAttributeWriter dst = points.attributes_for_write()->lookup_or_add_for_write_only_span( attribute_id, ATTR_DOMAIN_POINT, attribute_kind.data_type); BLI_assert(dst); attribute_math::convert_to_static_type(attribute_kind.data_type, [&](auto dummy) { using T = decltype(dummy); - copy_attribute_to_points(src.typed<T>(), selection, dst.as_span().typed<T>()); + copy_attribute_to_points(src.typed<T>(), selection, dst.span.typed<T>()); }); - dst.save(); + dst.finish(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 62cd1d8ac3a..083a505539a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -24,7 +24,7 @@ static Map<AttributeIDRef, AttributeMetaData> get_final_attribute_info( Map<AttributeIDRef, AttributeMetaData> info; for (const GeometryComponent *component : components) { - component->attribute_foreach( + component->attributes()->for_all( [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { if (attribute_id.is_named() && ignored_attributes.contains(attribute_id.name())) { return true; @@ -56,11 +56,11 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components, int offset = 0; for (const GeometryComponent *component : src_components) { - const int domain_num = component->attribute_domain_num(domain); + const int domain_num = component->attribute_domain_size(domain); if (domain_num == 0) { continue; } - GVArray read_attribute = component->attribute_get_for_read( + GVArray read_attribute = component->attributes()->lookup_or_default( attribute_id, domain, data_type, nullptr); GVArraySpan src_span{read_attribute}; @@ -83,15 +83,15 @@ static void join_attributes(Span<const GeometryComponent *> src_components, const AttributeIDRef attribute_id = item.key; const AttributeMetaData &meta_data = item.value; - OutputAttribute write_attribute = result.attribute_try_get_for_output_only( - attribute_id, meta_data.domain, meta_data.data_type); + GSpanAttributeWriter write_attribute = + result.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, meta_data.domain, meta_data.data_type); if (!write_attribute) { continue; } - GMutableSpan dst_span = write_attribute.as_span(); fill_new_attribute( - src_components, attribute_id, meta_data.data_type, meta_data.domain, dst_span); - write_attribute.save(); + src_components, attribute_id, meta_data.data_type, meta_data.domain, write_attribute.span); + write_attribute.finish(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc index 5875606da97..ca613ae009b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc @@ -71,7 +71,7 @@ class MaterialSelectionFieldInput final : public GeometryFieldInput { Array<bool> selection(mesh->totpoly); select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection); - return mesh_component.attribute_try_adapt_domain<bool>( + return mesh_component.attributes()->adapt_domain<bool>( VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_FACE, domain); return nullptr; diff --git a/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc b/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc index 1def4089115..4bc84a7a08a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc @@ -39,7 +39,7 @@ static PointCloud *pointcloud_merge_by_distance(const PointCloudComponent &src_p const float merge_distance, const Field<bool> &selection_field) { - const int src_num = src_points.attribute_domain_num(ATTR_DOMAIN_POINT); + const int src_num = src_points.attribute_domain_size(ATTR_DOMAIN_POINT); GeometryComponentFieldContext context{src_points, ATTR_DOMAIN_POINT}; FieldEvaluator evaluator{context, src_num}; evaluator.add(selection_field); @@ -57,7 +57,7 @@ static std::optional<Mesh *> mesh_merge_by_distance_connected(const MeshComponen const float merge_distance, const Field<bool> &selection_field) { - const int src_num = mesh_component.attribute_domain_num(ATTR_DOMAIN_POINT); + const int src_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT); Array<bool> selection(src_num); GeometryComponentFieldContext context{mesh_component, ATTR_DOMAIN_POINT}; FieldEvaluator evaluator{context, src_num}; @@ -72,7 +72,7 @@ static std::optional<Mesh *> mesh_merge_by_distance_all(const MeshComponent &mes const float merge_distance, const Field<bool> &selection_field) { - const int src_num = mesh_component.attribute_domain_num(ATTR_DOMAIN_POINT); + const int src_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT); GeometryComponentFieldContext context{mesh_component, ATTR_DOMAIN_POINT}; FieldEvaluator evaluator{context, src_num}; evaluator.add(selection_field); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc index b882d4bdf09..cb79ef93de9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc @@ -480,53 +480,49 @@ static void calculate_selection_outputs(Mesh *mesh, const ConeConfig &config, ConeAttributeOutputs &attribute_outputs) { - MeshComponent mesh_component; - mesh_component.replace(mesh, GeometryOwnershipType::Editable); + MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*mesh); /* Populate "Top" selection output. */ if (attribute_outputs.top_id) { const bool face = !config.top_is_point && config.fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE; - OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>( + SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_only_span<bool>( attribute_outputs.top_id.get(), face ? ATTR_DOMAIN_FACE : ATTR_DOMAIN_POINT); - MutableSpan<bool> selection = attribute.as_span(); if (config.top_is_point) { - selection[config.first_vert] = true; + selection.span[config.first_vert] = true; } else { - selection.slice(0, face ? config.top_faces_len : config.circle_segments).fill(true); + selection.span.slice(0, face ? config.top_faces_len : config.circle_segments).fill(true); } - attribute.save(); + selection.finish(); } /* Populate "Bottom" selection output. */ if (attribute_outputs.bottom_id) { const bool face = !config.bottom_is_point && config.fill_type != GEO_NODE_MESH_CIRCLE_FILL_NONE; - OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>( + SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_only_span<bool>( attribute_outputs.bottom_id.get(), face ? ATTR_DOMAIN_FACE : ATTR_DOMAIN_POINT); - MutableSpan<bool> selection = attribute.as_span(); if (config.bottom_is_point) { - selection[config.last_vert] = true; + selection.span[config.last_vert] = true; } else if (face) { - selection.slice(config.bottom_faces_start, config.bottom_faces_len).fill(true); + selection.span.slice(config.bottom_faces_start, config.bottom_faces_len).fill(true); } else { - selection.slice(config.last_ring_verts_start + 1, config.circle_segments).fill(true); + selection.span.slice(config.last_ring_verts_start + 1, config.circle_segments).fill(true); } - attribute.save(); + selection.finish(); } /* Populate "Side" selection output. */ if (attribute_outputs.side_id) { - OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>( + SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_only_span<bool>( attribute_outputs.side_id.get(), ATTR_DOMAIN_FACE); - MutableSpan<bool> selection = attribute.as_span(); - selection.slice(config.side_faces_start, config.side_faces_len).fill(true); - attribute.save(); + selection.span.slice(config.side_faces_start, config.side_faces_len).fill(true); + selection.finish(); } } @@ -540,11 +536,11 @@ static void calculate_selection_outputs(Mesh *mesh, */ static void calculate_cone_uvs(Mesh *mesh, const ConeConfig &config) { - MeshComponent mesh_component; - mesh_component.replace(mesh, GeometryOwnershipType::Editable); - OutputAttribute_Typed<float2> uv_attribute = - mesh_component.attribute_try_get_for_output_only<float2>("uv_map", ATTR_DOMAIN_CORNER); - MutableSpan<float2> uvs = uv_attribute.as_span(); + MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*mesh); + + SpanAttributeWriter<float2> uv_attribute = attributes.lookup_or_add_for_write_only_span<float2>( + "uv_map", ATTR_DOMAIN_CORNER); + MutableSpan<float2> uvs = uv_attribute.span; Array<float2> circle(config.circle_segments); float angle = 0.0f; @@ -654,7 +650,7 @@ static void calculate_cone_uvs(Mesh *mesh, const ConeConfig &config) } } - uv_attribute.save(); + uv_attribute.finish(); } static Mesh *create_vertex_mesh() diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc index 523dbd5dac2..9baf0b3171e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc @@ -18,23 +18,22 @@ namespace blender::nodes { static void calculate_uvs( Mesh *mesh, Span<MVert> verts, Span<MLoop> loops, const float size_x, const float size_y) { - MeshComponent mesh_component; - mesh_component.replace(mesh, GeometryOwnershipType::Editable); - OutputAttribute_Typed<float2> uv_attribute = - mesh_component.attribute_try_get_for_output_only<float2>("uv_map", ATTR_DOMAIN_CORNER); - MutableSpan<float2> uvs = uv_attribute.as_span(); + MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*mesh); + + SpanAttributeWriter<float2> uv_attribute = attributes.lookup_or_add_for_write_only_span<float2>( + "uv_map", ATTR_DOMAIN_CORNER); const float dx = (size_x == 0.0f) ? 0.0f : 1.0f / size_x; const float dy = (size_y == 0.0f) ? 0.0f : 1.0f / size_y; threading::parallel_for(loops.index_range(), 1024, [&](IndexRange range) { for (const int i : range) { const float3 &co = verts[loops[i].v].co; - uvs[i].x = (co.x + size_x * 0.5f) * dx; - uvs[i].y = (co.y + size_y * 0.5f) * dy; + uv_attribute.span[i].x = (co.x + size_x * 0.5f) * dx; + uv_attribute.span[i].y = (co.y + size_y * 0.5f) * dy; } }); - uv_attribute.save(); + uv_attribute.finish(); } Mesh *create_grid_mesh(const int verts_x, diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index 4e0e5c7c912..f78752387c6 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -220,11 +220,11 @@ static void calculate_sphere_faces(MutableSpan<MLoop> loops, static void calculate_sphere_uvs(Mesh *mesh, const float segments, const float rings) { - MeshComponent mesh_component; - mesh_component.replace(mesh, GeometryOwnershipType::Editable); - OutputAttribute_Typed<float2> uv_attribute = - mesh_component.attribute_try_get_for_output_only<float2>("uv_map", ATTR_DOMAIN_CORNER); - MutableSpan<float2> uvs = uv_attribute.as_span(); + MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*mesh); + + SpanAttributeWriter<float2> uv_attribute = attributes.lookup_or_add_for_write_only_span<float2>( + "uv_map", ATTR_DOMAIN_CORNER); + MutableSpan<float2> uvs = uv_attribute.span; int loop_index = 0; const float dy = 1.0f / rings; @@ -254,7 +254,7 @@ static void calculate_sphere_uvs(Mesh *mesh, const float segments, const float r uvs[loop_index++] = float2(segment / segments, 1.0f - dy); } - uv_attribute.save(); + uv_attribute.finish(); } static Mesh *create_uv_sphere_mesh(const float radius, const int segments, const int rings) diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc index ec6acf55dd8..f6ee3d00dee 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc @@ -25,7 +25,7 @@ static void node_geo_exec(GeoNodeExecParams params) const MeshComponent &component = *geometry_set.get_component_for_read<MeshComponent>(); GeometryComponentFieldContext context{component, ATTR_DOMAIN_EDGE}; - fn::FieldEvaluator evaluator{context, component.attribute_domain_num(ATTR_DOMAIN_EDGE)}; + fn::FieldEvaluator evaluator{context, component.attribute_domain_size(ATTR_DOMAIN_EDGE)}; evaluator.add(params.get_input<Field<bool>>("Selection")); evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_as_mask(0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc index 7463eb01471..8e621d3ed97 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc @@ -66,7 +66,7 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set, return; } GeometryComponentFieldContext field_context{*mesh_component, domain}; - const int domain_num = mesh_component->attribute_domain_num(domain); + const int domain_num = mesh_component->attribute_domain_size(domain); if (domain_num == 0) { geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES}); return; @@ -83,20 +83,20 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set, PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size()); geometry_set.replace_pointcloud(pointcloud); - PointCloudComponent &point_component = - geometry_set.get_component_for_write<PointCloudComponent>(); + MutableAttributeAccessor pointcloud_attributes = bke::pointcloud_attributes_for_write( + *pointcloud); - OutputAttribute position = point_component.attribute_try_get_for_output_only( + GSpanAttributeWriter position = pointcloud_attributes.lookup_or_add_for_write_only_span( "position", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); materialize_compressed_to_uninitialized_threaded( - evaluator.get_evaluated(0), selection, position.as_span()); - position.save(); + evaluator.get_evaluated(0), selection, position.span); + position.finish(); - OutputAttribute radius = point_component.attribute_try_get_for_output_only( + GSpanAttributeWriter radius = pointcloud_attributes.lookup_or_add_for_write_only_span( "radius", ATTR_DOMAIN_POINT, CD_PROP_FLOAT); materialize_compressed_to_uninitialized_threaded( - evaluator.get_evaluated(1), selection, radius.as_span()); - radius.save(); + evaluator.get_evaluated(1), selection, radius.span); + radius.finish(); Map<AttributeIDRef, AttributeKind> attributes; geometry_set.gather_attributes_for_propagation( @@ -106,12 +106,12 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set, for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; const eCustomDataType data_type = entry.value.data_type; - GVArray src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type); - OutputAttribute dst = point_component.attribute_try_get_for_output_only( + GVArray src = mesh_component->attributes()->lookup_or_default(attribute_id, domain, data_type); + GSpanAttributeWriter dst = pointcloud_attributes.lookup_or_add_for_write_only_span( attribute_id, ATTR_DOMAIN_POINT, data_type); if (dst && src) { - materialize_compressed_to_uninitialized_threaded(src, selection, dst.as_span()); - dst.save(); + materialize_compressed_to_uninitialized_threaded(src, selection, dst.span); + dst.finish(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_points.cc b/source/blender/nodes/geometry/nodes/node_geo_points.cc index da414960e1d..dd32e6714f4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points.cc @@ -72,19 +72,20 @@ static void node_geo_exec(GeoNodeExecParams params) PointCloud *new_point_cloud = BKE_pointcloud_new_nomain(count); GeometrySet geometry_set = GeometrySet::create_with_pointcloud(new_point_cloud); PointCloudComponent &points = geometry_set.get_component_for_write<PointCloudComponent>(); - OutputAttribute_Typed<float3> output_position = points.attribute_try_get_for_output_only<float3>( + MutableAttributeAccessor attributes = *points.attributes_for_write(); + AttributeWriter<float3> output_position = attributes.lookup_or_add_for_write<float3>( "position", ATTR_DOMAIN_POINT); - OutputAttribute_Typed<float> output_radii = points.attribute_try_get_for_output_only<float>( + AttributeWriter<float> output_radii = attributes.lookup_or_add_for_write<float>( "radius", ATTR_DOMAIN_POINT); PointsFieldContext context{count}; fn::FieldEvaluator evaluator{context, count}; - evaluator.add_with_destination(position_field, output_position.as_span()); - evaluator.add_with_destination(radius_field, output_radii.as_span()); + evaluator.add_with_destination(position_field, output_position.varray); + evaluator.add_with_destination(radius_field, output_radii.varray); evaluator.evaluate(); - output_position.save(); - output_radii.save(); + output_position.finish(); + output_radii.finish(); params.set_output("Geometry", std::move(geometry_set)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc index 95ff53b7146..9cc64d4bc44 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc @@ -38,7 +38,7 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set, } GeometryComponentFieldContext field_context{*point_component, ATTR_DOMAIN_POINT}; - const int domain_num = point_component->attribute_domain_num(ATTR_DOMAIN_POINT); + const int domain_num = point_component->attribute_domain_size(ATTR_DOMAIN_POINT); if (domain_num == 0) { geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES}); return; @@ -60,18 +60,19 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set, for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; const eCustomDataType data_type = entry.value.data_type; - GVArray src = point_component->attribute_get_for_read( - attribute_id, ATTR_DOMAIN_POINT, data_type); - OutputAttribute dst = mesh_component.attribute_try_get_for_output_only( + GVArray src = point_component->attributes()->lookup_or_default( attribute_id, ATTR_DOMAIN_POINT, data_type); + GSpanAttributeWriter dst = + mesh_component.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, ATTR_DOMAIN_POINT, data_type); if (dst && src) { attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); VArray<T> src_typed = src.typed<T>(); VArraySpan<T> src_typed_span{src_typed}; - copy_attribute_to_vertices(src_typed_span, selection, dst.as_span().typed<T>()); + copy_attribute_to_vertices(src_typed_span, selection, dst.span.typed<T>()); }); - dst.save(); + dst.finish(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc index 42cee4c0efe..28a01a5cbce 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc @@ -163,12 +163,15 @@ static void gather_point_data_from_component(GeoNodeExecParams ¶ms, Vector<float3> &r_positions, Vector<float> &r_radii) { - VArray<float3> positions = component.attribute_get_for_read<float3>( + if (component.is_empty()) { + return; + } + VArray<float3> positions = component.attributes()->lookup_or_default<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); Field<float> radius_field = params.get_input<Field<float>>("Radius"); GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_POINT); + const int domain_num = component.attribute_domain_size(ATTR_DOMAIN_POINT); r_positions.resize(r_positions.size() + domain_num); positions.materialize(r_positions.as_mutable_span().take_back(domain_num)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc index a92cee2d066..f81748da587 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc @@ -312,8 +312,8 @@ class RaycastFunction : public fn::MultiFunction { } const MeshComponent &mesh_component = *target_.get_component_for_read<MeshComponent>(); target_context_.emplace(GeometryComponentFieldContext{mesh_component, domain_}); - const int domain_num = mesh_component.attribute_domain_num(domain_); - target_evaluator_ = std::make_unique<FieldEvaluator>(*target_context_, domain_num); + const int domain_size = mesh_component.attribute_domain_size(domain_); + target_evaluator_ = std::make_unique<FieldEvaluator>(*target_context_, domain_size); target_evaluator_->add(std::move(src_field)); target_evaluator_->evaluate(); target_data_ = &target_evaluator_->get_evaluated(0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc index da42b8c5ee0..ee279ba58f9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc @@ -39,7 +39,7 @@ static void node_geo_exec(GeoNodeExecParams params) /* First check if the attribute exists before getting write access, * to avoid potentially expensive unnecessary copies. */ const GeometryComponent &read_only_component = *geometry_set.get_component_for_read(type); - if (read_only_component.attribute_exists(name)) { + if (read_only_component.attributes()->contains(name)) { attribute_exists = true; } else { @@ -47,7 +47,7 @@ static void node_geo_exec(GeoNodeExecParams params) } GeometryComponent &component = geometry_set.get_component_for_write(type); - if (!component.attribute_try_delete(name)) { + if (!component.attributes_for_write()->remove(name)) { cannot_delete = true; } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc index 37533a7b99a..fc3cb7006bb 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc @@ -75,12 +75,12 @@ static void set_position_in_component(CurveComponent &component, const Field<float3> &offset_field) { GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_POINT); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT); + if (domain_size == 0) { return; } - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); evaluator.add(position_field); evaluator.add(offset_field); @@ -146,8 +146,8 @@ static void node_geo_exec(GeoNodeExecParams params) } has_curves = true; const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>(); - if (!component.attribute_exists("handle_left") || - !component.attribute_exists("handle_right")) { + const AttributeAccessor attributes = *component.attributes(); + if (!attributes.contains("handle_left") || !attributes.contains("handle_right")) { return; } has_bezier = true; diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc index 4c84093bfcb..90411baac3e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc @@ -20,21 +20,22 @@ static void set_radius_in_component(GeometryComponent &component, const Field<bool> &selection_field, const Field<float> &radius_field) { - GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_POINT); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT); + if (domain_size == 0) { return; } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - OutputAttribute_Typed<float> radii = component.attribute_try_get_for_output_only<float>( - "radius", ATTR_DOMAIN_POINT); + AttributeWriter<float> radii = attributes.lookup_or_add_for_write<float>("radius", + ATTR_DOMAIN_POINT); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); - evaluator.add_with_destination(radius_field, radii.varray()); + evaluator.add_with_destination(radius_field, radii.varray); evaluator.evaluate(); - radii.save(); + radii.finish(); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc index 8b1e5935a61..2211ac62727 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc @@ -16,21 +16,23 @@ static void set_tilt_in_component(GeometryComponent &component, const Field<bool> &selection_field, const Field<float> &tilt_field) { - GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_POINT); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT); + if (domain_size == 0) { return; } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + + GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - OutputAttribute_Typed<float> tilts = component.attribute_try_get_for_output_only<float>( - "tilt", ATTR_DOMAIN_POINT); + AttributeWriter<float> tilts = attributes.lookup_or_add_for_write<float>("tilt", + ATTR_DOMAIN_POINT); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); - evaluator.add_with_destination(tilt_field, tilts.varray()); + evaluator.add_with_destination(tilt_field, tilts.varray); evaluator.evaluate(); - tilts.save(); + tilts.finish(); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc index a7f17c02ce8..fbb2ecbb799 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc @@ -19,34 +19,34 @@ static void set_id_in_component(GeometryComponent &component, const eAttrDomain domain = (component.type() == GEO_COMPONENT_TYPE_INSTANCES) ? ATTR_DOMAIN_INSTANCE : ATTR_DOMAIN_POINT; - GeometryComponentFieldContext field_context{component, domain}; - const int domain_num = component.attribute_domain_num(domain); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(domain); + if (domain_size == 0) { return; } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + GeometryComponentFieldContext field_context{component, domain}; - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); /* Since adding the ID attribute can change the result of the field evaluation (the random value * node uses the index if the ID is unavailable), make sure that it isn't added before evaluating * the field. However, as an optimization, use a faster code path when it already exists. */ - if (component.attribute_exists("id")) { - OutputAttribute_Typed<int> id_attribute = component.attribute_try_get_for_output_only<int>( - "id", domain); - evaluator.add_with_destination(id_field, id_attribute.varray()); + if (attributes.contains("id")) { + AttributeWriter<int> id_attribute = attributes.lookup_or_add_for_write<int>("id", domain); + evaluator.add_with_destination(id_field, id_attribute.varray); evaluator.evaluate(); - id_attribute.save(); + id_attribute.finish(); } else { evaluator.add(id_field); evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); const VArray<int> result_ids = evaluator.get_evaluated<int>(0); - OutputAttribute_Typed<int> id_attribute = component.attribute_try_get_for_output_only<int>( - "id", domain); - result_ids.materialize(selection, id_attribute.as_span()); - id_attribute.save(); + SpanAttributeWriter<int> id_attribute = attributes.lookup_or_add_for_write_span<int>("id", + domain); + result_ids.materialize(selection, id_attribute.span); + id_attribute.finish(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc b/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc index 58613dae832..0dc89bb7ef4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc @@ -16,20 +16,21 @@ static void set_material_index_in_component(GeometryComponent &component, const Field<bool> &selection_field, const Field<int> &index_field) { - GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_FACE}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_FACE); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_FACE); + if (domain_size == 0) { return; } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_FACE}; - OutputAttribute_Typed<int> indices = component.attribute_try_get_for_output_only<int>( - "material_index", ATTR_DOMAIN_FACE); + AttributeWriter<int> indices = attributes.lookup_or_add_for_write<int>("material_index", + ATTR_DOMAIN_FACE); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); - evaluator.add_with_destination(index_field, indices.varray()); + evaluator.add_with_destination(index_field, indices.varray); evaluator.evaluate(); - indices.save(); + indices.finish(); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc index 571bead9743..da7977a4fb4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc @@ -20,21 +20,22 @@ static void set_radius_in_component(GeometryComponent &component, const Field<bool> &selection_field, const Field<float> &radius_field) { - GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_POINT); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT); + if (domain_size == 0) { return; } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT}; - OutputAttribute_Typed<float> radii = component.attribute_try_get_for_output_only<float>( - "radius", ATTR_DOMAIN_POINT); + AttributeWriter<float> radii = attributes.lookup_or_add_for_write<float>("radius", + ATTR_DOMAIN_POINT); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); - evaluator.add_with_destination(radius_field, radii.varray()); + evaluator.add_with_destination(radius_field, radii.varray); evaluator.evaluate(); - radii.save(); + radii.finish(); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc index 1935409b3e5..880252de4fa 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc @@ -25,12 +25,10 @@ static void node_declare(NodeDeclarationBuilder &b) static void set_computed_position_and_offset(GeometryComponent &component, const VArray<float3> &in_positions, const VArray<float3> &in_offsets, - const eAttrDomain domain, const IndexMask selection) { - - OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output<float3>( - "position", domain, {0, 0, 0}); + MutableAttributeAccessor attributes = *component.attributes_for_write(); + AttributeWriter<float3> positions = attributes.lookup_for_write<float3>("position"); const int grain_size = 10000; @@ -38,7 +36,7 @@ static void set_computed_position_and_offset(GeometryComponent &component, case GEO_COMPONENT_TYPE_MESH: { Mesh *mesh = static_cast<MeshComponent &>(component).get_for_write(); MutableSpan<MVert> mverts{mesh->mvert, mesh->totvert}; - if (in_positions.is_same(positions.varray())) { + if (in_positions.is_same(positions.varray)) { devirtualize_varray(in_offsets, [&](const auto in_offsets) { threading::parallel_for( selection.index_range(), grain_size, [&](const IndexRange range) { @@ -67,18 +65,13 @@ static void set_computed_position_and_offset(GeometryComponent &component, CurveComponent &curve_component = static_cast<CurveComponent &>(component); Curves &curves_id = *curve_component.get_for_write(); bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); - if (component.attribute_exists("handle_right") && - component.attribute_exists("handle_left")) { - OutputAttribute_Typed<float3> handle_right_attribute = - component.attribute_try_get_for_output<float3>( - "handle_right", ATTR_DOMAIN_POINT, {0, 0, 0}); - OutputAttribute_Typed<float3> handle_left_attribute = - component.attribute_try_get_for_output<float3>( - "handle_left", ATTR_DOMAIN_POINT, {0, 0, 0}); - MutableSpan<float3> handle_right = handle_right_attribute.as_span(); - MutableSpan<float3> handle_left = handle_left_attribute.as_span(); - - MutableSpan<float3> out_positions_span = positions.as_span(); + if (attributes.contains("handle_right") && attributes.contains("handle_left")) { + SpanAttributeWriter<float3> handle_right_attribute = + attributes.lookup_or_add_for_write_span<float3>("handle_right", ATTR_DOMAIN_POINT); + SpanAttributeWriter<float3> handle_left_attribute = + attributes.lookup_or_add_for_write_span<float3>("handle_left", ATTR_DOMAIN_POINT); + + MutableVArraySpan<float3> out_positions_span = positions.varray; devirtualize_varray2( in_positions, in_offsets, [&](const auto in_positions, const auto in_offsets) { threading::parallel_for( @@ -86,15 +79,16 @@ static void set_computed_position_and_offset(GeometryComponent &component, for (const int i : selection.slice(range)) { const float3 new_position = in_positions[i] + in_offsets[i]; const float3 delta = new_position - out_positions_span[i]; - handle_right[i] += delta; - handle_left[i] += delta; + handle_right_attribute.span[i] += delta; + handle_left_attribute.span[i] += delta; out_positions_span[i] = new_position; } }); }); - handle_right_attribute.save(); - handle_left_attribute.save(); + out_positions_span.save(); + handle_right_attribute.finish(); + handle_left_attribute.finish(); /* Automatic Bezier handles must be recalculated based on the new positions. */ curves.calculate_bezier_auto_handles(); @@ -105,8 +99,8 @@ static void set_computed_position_and_offset(GeometryComponent &component, } } default: { - MutableSpan<float3> out_positions_span = positions.as_span(); - if (in_positions.is_same(positions.varray())) { + MutableVArraySpan<float3> out_positions_span = positions.varray; + if (in_positions.is_same(positions.varray)) { devirtualize_varray(in_offsets, [&](const auto in_offsets) { threading::parallel_for( selection.index_range(), grain_size, [&](const IndexRange range) { @@ -127,11 +121,12 @@ static void set_computed_position_and_offset(GeometryComponent &component, }); }); } + out_positions_span.save(); break; } } - positions.save(); + positions.finish(); } static void set_position_in_component(GeometryComponent &component, @@ -142,21 +137,22 @@ static void set_position_in_component(GeometryComponent &component, eAttrDomain domain = component.type() == GEO_COMPONENT_TYPE_INSTANCES ? ATTR_DOMAIN_INSTANCE : ATTR_DOMAIN_POINT; GeometryComponentFieldContext field_context{component, domain}; - const int domain_num = component.attribute_domain_num(domain); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(domain); + if (domain_size == 0) { return; } - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); evaluator.add(position_field); evaluator.add(offset_field); evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const VArray<float3> positions_input = evaluator.get_evaluated<float3>(0); const VArray<float3> offsets_input = evaluator.get_evaluated<float3>(1); - set_computed_position_and_offset(component, positions_input, offsets_input, domain, selection); + set_computed_position_and_offset(component, positions_input, offsets_input, selection); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc index b98fbd0a0fe..e0cf0f98d58 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc @@ -16,21 +16,23 @@ static void set_smooth_in_component(GeometryComponent &component, const Field<bool> &selection_field, const Field<bool> &shade_field) { - GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_FACE}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_FACE); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_FACE); + if (domain_size == 0) { return; } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + + GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_FACE}; - OutputAttribute_Typed<bool> shades = component.attribute_try_get_for_output_only<bool>( - "shade_smooth", ATTR_DOMAIN_FACE); + AttributeWriter<bool> shades = attributes.lookup_or_add_for_write<bool>("shade_smooth", + ATTR_DOMAIN_FACE); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); - evaluator.add_with_destination(shade_field, shades.varray()); + evaluator.add_with_destination(shade_field, shades.varray); evaluator.evaluate(); - shades.save(); + shades.finish(); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc index 976857883f0..a35d8d66558 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc @@ -16,21 +16,23 @@ static void set_cyclic_in_component(GeometryComponent &component, const Field<bool> &selection_field, const Field<bool> &cyclic_field) { - GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_CURVE}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_CURVE); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_CURVE); + if (domain_size == 0) { return; } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + + GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_CURVE}; - OutputAttribute_Typed<bool> cyclics = component.attribute_try_get_for_output_only<bool>( - "cyclic", ATTR_DOMAIN_CURVE); + AttributeWriter<bool> cyclics = attributes.lookup_or_add_for_write<bool>("cyclic", + ATTR_DOMAIN_CURVE); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); - evaluator.add_with_destination(cyclic_field, cyclics.varray()); + evaluator.add_with_destination(cyclic_field, cyclics.varray); evaluator.evaluate(); - cyclics.save(); + cyclics.finish(); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc index 8b665376c01..fcebc1116d7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc @@ -16,21 +16,23 @@ static void set_resolution_in_component(GeometryComponent &component, const Field<bool> &selection_field, const Field<int> &resolution_field) { - GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_CURVE}; - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_CURVE); - if (domain_num == 0) { + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_CURVE); + if (domain_size == 0) { return; } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + + GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_CURVE}; - OutputAttribute_Typed<int> resolutions = component.attribute_try_get_for_output_only<int>( - "resolution", ATTR_DOMAIN_CURVE); + AttributeWriter<int> resolutions = attributes.lookup_or_add_for_write<int>("resolution", + ATTR_DOMAIN_CURVE); - fn::FieldEvaluator evaluator{field_context, domain_num}; + fn::FieldEvaluator evaluator{field_context, domain_size}; evaluator.set_selection(selection_field); - evaluator.add_with_destination(resolution_field, resolutions.varray()); + evaluator.add_with_destination(resolution_field, resolutions.varray); evaluator.evaluate(); - resolutions.save(); + resolutions.finish(); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc index abac6d8d6b3..69a4fad10e2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc @@ -87,9 +87,14 @@ static void try_capture_field_on_geometry(GeometryComponent &component, const eAttrDomain domain, const GField &field) { + const int domain_size = component.attribute_domain_size(domain); + if (domain_size == 0) { + return; + } + MutableAttributeAccessor attributes = *component.attributes_for_write(); + GeometryComponentFieldContext field_context{component, domain}; - const int domain_num = component.attribute_domain_num(domain); - const IndexMask mask{IndexMask(domain_num)}; + const IndexMask mask{IndexMask(domain_size)}; const CPPType &type = field.cpp_type(); const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(type); @@ -97,28 +102,28 @@ static void try_capture_field_on_geometry(GeometryComponent &component, /* Could avoid allocating a new buffer if: * - We are writing to an attribute that exists already. * - The field does not depend on that attribute (we can't easily check for that yet). */ - void *buffer = MEM_mallocN(type.size() * domain_num, __func__); + void *buffer = MEM_mallocN(type.size() * domain_size, __func__); fn::FieldEvaluator evaluator{field_context, &mask}; - evaluator.add_with_destination(field, GMutableSpan{type, buffer, domain_num}); + evaluator.add_with_destination(field, GMutableSpan{type, buffer, domain_size}); evaluator.evaluate(); - component.attribute_try_delete(name); - if (component.attribute_exists(name)) { - WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(name); + attributes.remove(name); + if (attributes.contains(name)) { + GAttributeWriter write_attribute = attributes.lookup_for_write(name); if (write_attribute && write_attribute.domain == domain && write_attribute.varray.type() == type) { write_attribute.varray.set_all(buffer); - write_attribute.tag_modified_fn(); + write_attribute.finish(); } else { /* Cannot change type of built-in attribute. */ } - type.destruct_n(buffer, domain_num); + type.destruct_n(buffer, domain_size); MEM_freeN(buffer); } else { - if (!component.attribute_try_create(name, domain, data_type, AttributeInitMove{buffer})) { + if (!attributes.add(name, domain, data_type, bke::AttributeInitMove{buffer})) { MEM_freeN(buffer); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc index 94d5d7f946f..afd7db6604d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc @@ -335,13 +335,14 @@ static void create_attributes(GeoNodeExecParams ¶ms, const TextLayout &layout, InstancesComponent &instances) { + MutableAttributeAccessor attributes = *instances.attributes_for_write(); + if (params.output_is_required("Line")) { StrongAnonymousAttributeID line_id = StrongAnonymousAttributeID("Line"); - OutputAttribute_Typed<int> line_attribute = instances.attribute_try_get_for_output_only<int>( + SpanAttributeWriter<int> line_attribute = attributes.lookup_or_add_for_write_only_span<int>( line_id.get(), ATTR_DOMAIN_INSTANCE); - MutableSpan<int> lines = line_attribute.as_span(); - lines.copy_from(layout.line_numbers); - line_attribute.save(); + line_attribute.span.copy_from(layout.line_numbers); + line_attribute.finish(); params.set_output("Line", AnonymousAttributeFieldInput::Create<int>(std::move(line_id), params.attribute_producer_name())); @@ -349,15 +350,14 @@ static void create_attributes(GeoNodeExecParams ¶ms, if (params.output_is_required("Pivot Point")) { StrongAnonymousAttributeID pivot_id = StrongAnonymousAttributeID("Pivot"); - OutputAttribute_Typed<float3> pivot_attribute = - instances.attribute_try_get_for_output_only<float3>(pivot_id.get(), ATTR_DOMAIN_INSTANCE); - MutableSpan<float3> pivots = pivot_attribute.as_span(); + SpanAttributeWriter<float3> pivot_attribute = + attributes.lookup_or_add_for_write_only_span<float3>(pivot_id.get(), ATTR_DOMAIN_INSTANCE); for (const int i : layout.char_codes.index_range()) { - pivots[i] = layout.pivot_points.lookup(layout.char_codes[i]); + pivot_attribute.span[i] = layout.pivot_points.lookup(layout.char_codes[i]); } - pivot_attribute.save(); + pivot_attribute.finish(); params.set_output("Pivot Point", AnonymousAttributeFieldInput::Create<float3>( std::move(pivot_id), params.attribute_producer_name())); diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index 9eda5bb34ff..eda6a51d412 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -6,6 +6,7 @@ #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" +#include "BKE_attribute.hh" #include "BKE_mesh.h" #include "BKE_subdiv.h" #include "BKE_subdiv_mesh.h" @@ -79,10 +80,11 @@ static void write_vertex_creases(Mesh &mesh, const VArray<float> &crease_varray) static void write_edge_creases(MeshComponent &mesh, const VArray<float> &crease_varray) { - OutputAttribute_Typed<float> attribute = mesh.attribute_try_get_for_output_only<float>( - "crease", ATTR_DOMAIN_EDGE); - materialize_and_clamp_creases(crease_varray, attribute.as_span()); - attribute.save(); + bke::SpanAttributeWriter<float> attribute = + mesh.attributes_for_write()->lookup_or_add_for_write_only_span<float>("crease", + ATTR_DOMAIN_EDGE); + materialize_and_clamp_creases(crease_varray, attribute.span); + attribute.finish(); } static bool varray_is_nonzero(const VArray<float> &varray) @@ -118,8 +120,8 @@ static void node_geo_exec(GeoNodeExecParams params) } const MeshComponent &mesh_component = *geometry_set.get_component_for_read<MeshComponent>(); - const int verts_num = mesh_component.attribute_domain_num(ATTR_DOMAIN_POINT); - const int edges_num = mesh_component.attribute_domain_num(ATTR_DOMAIN_EDGE); + const int verts_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT); + const int edges_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_EDGE); if (verts_num == 0 || edges_num == 0) { return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc index 0af6c76feaf..cd75822f665 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc @@ -365,7 +365,7 @@ static bool component_is_available(const GeometrySet &geometry, if (component.is_empty()) { return false; } - return component.attribute_domain_num(domain) != 0; + return component.attribute_domain_size(domain) != 0; } /** @@ -433,7 +433,7 @@ class NearestInterpolatedTransferFunction : public fn::MultiFunction { { const MeshComponent &mesh_component = *source_.get_component_for_read<MeshComponent>(); source_context_.emplace(GeometryComponentFieldContext{mesh_component, domain_}); - const int domain_num = mesh_component.attribute_domain_num(domain_); + const int domain_num = mesh_component.attribute_domain_size(domain_); source_evaluator_ = std::make_unique<FieldEvaluator>(*source_context_, domain_num); source_evaluator_->add(src_field_); source_evaluator_->evaluate(); @@ -578,7 +578,7 @@ class NearestTransferFunction : public fn::MultiFunction { { if (use_mesh_) { const MeshComponent &mesh = *source_.get_component_for_read<MeshComponent>(); - const int domain_num = mesh.attribute_domain_num(domain_); + const int domain_num = mesh.attribute_domain_size(domain_); mesh_context_.emplace(GeometryComponentFieldContext(mesh, domain_)); mesh_evaluator_ = std::make_unique<FieldEvaluator>(*mesh_context_, domain_num); mesh_evaluator_->add(src_field_); @@ -588,7 +588,7 @@ class NearestTransferFunction : public fn::MultiFunction { if (use_points_) { const PointCloudComponent &points = *source_.get_component_for_read<PointCloudComponent>(); - const int domain_num = points.attribute_domain_num(domain_); + const int domain_num = points.attribute_domain_size(domain_); point_context_.emplace(GeometryComponentFieldContext(points, domain_)); point_evaluator_ = std::make_unique<FieldEvaluator>(*point_context_, domain_num); point_evaluator_->add(src_field_); @@ -658,7 +658,7 @@ class IndexTransferFunction : public fn::MultiFunction { if (component == nullptr) { return; } - const int domain_num = component->attribute_domain_num(domain_); + const int domain_num = component->attribute_domain_size(domain_); geometry_context_.emplace(GeometryComponentFieldContext(*component, domain_)); evaluator_ = std::make_unique<FieldEvaluator>(*geometry_context_, domain_num); evaluator_->add(src_field_); diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc index e47dc22da04..992470e8279 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc @@ -83,9 +83,9 @@ static void node_geo_exec(GeoNodeExecParams params) GeometryComponent &component = geometry_set.get_component_for_write<MeshComponent>(); const Mesh &mesh_in = *geometry_set.get_mesh_for_read(); - const int domain_num = component.attribute_domain_num(ATTR_DOMAIN_FACE); + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_FACE); GeometryComponentFieldContext context{component, ATTR_DOMAIN_FACE}; - FieldEvaluator evaluator{context, domain_num}; + FieldEvaluator evaluator{context, domain_size}; evaluator.add(selection_field); evaluator.evaluate(); const IndexMask selection = evaluator.get_evaluated_as_mask(0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc b/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc index feff6efc3f8..17413e64f7d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_uv_pack_islands.cc @@ -40,7 +40,7 @@ static VArray<float3> construct_uv_gvarray(const MeshComponent &component, return {}; } - const int face_num = component.attribute_domain_num(ATTR_DOMAIN_FACE); + const int face_num = component.attribute_domain_size(ATTR_DOMAIN_FACE); GeometryComponentFieldContext face_context{component, ATTR_DOMAIN_FACE}; FieldEvaluator face_evaluator{face_context, face_num}; face_evaluator.add(selection_field); @@ -50,7 +50,7 @@ static VArray<float3> construct_uv_gvarray(const MeshComponent &component, return {}; } - const int corner_num = component.attribute_domain_num(ATTR_DOMAIN_CORNER); + const int corner_num = component.attribute_domain_size(ATTR_DOMAIN_CORNER); GeometryComponentFieldContext corner_context{component, ATTR_DOMAIN_CORNER}; FieldEvaluator evaluator{corner_context, corner_num}; Array<float3> uv(corner_num); @@ -88,7 +88,7 @@ static VArray<float3> construct_uv_gvarray(const MeshComponent &component, GEO_uv_parametrizer_flush(handle); GEO_uv_parametrizer_delete(handle); - return component.attribute_try_adapt_domain<float3>( + return component.attributes()->adapt_domain<float3>( VArray<float3>::ForContainer(std::move(uv)), ATTR_DOMAIN_CORNER, domain); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc b/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc index 364106455b6..2ec14ad2d29 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc @@ -65,7 +65,7 @@ static VArray<float3> construct_uv_gvarray(const MeshComponent &component, return {}; } - const int face_num = component.attribute_domain_num(ATTR_DOMAIN_FACE); + const int face_num = component.attribute_domain_size(ATTR_DOMAIN_FACE); GeometryComponentFieldContext face_context{component, ATTR_DOMAIN_FACE}; FieldEvaluator face_evaluator{face_context, face_num}; face_evaluator.add(selection_field); @@ -75,7 +75,7 @@ static VArray<float3> construct_uv_gvarray(const MeshComponent &component, return {}; } - const int edge_num = component.attribute_domain_num(ATTR_DOMAIN_EDGE); + const int edge_num = component.attribute_domain_size(ATTR_DOMAIN_EDGE); GeometryComponentFieldContext edge_context{component, ATTR_DOMAIN_EDGE}; FieldEvaluator edge_evaluator{edge_context, edge_num}; edge_evaluator.add(seam_field); @@ -126,7 +126,7 @@ static VArray<float3> construct_uv_gvarray(const MeshComponent &component, GEO_uv_parametrizer_flush(handle); GEO_uv_parametrizer_delete(handle); - return component.attribute_try_adapt_domain<float3>( + return component.attributes()->adapt_domain<float3>( VArray<float3>::ForContainer(std::move(uv)), ATTR_DOMAIN_CORNER, domain); } diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc index 85dfdf03b82..cf7cbbdc4bf 100644 --- a/source/blender/nodes/intern/geometry_nodes_eval_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc @@ -228,7 +228,7 @@ GeometryValueLog::GeometryValueLog(const GeometrySet &geometry_set, bool log_ful all_component_types, true, [&](const bke::AttributeIDRef &attribute_id, - const AttributeMetaData &meta_data, + const bke::AttributeMetaData &meta_data, const GeometryComponent &UNUSED(component)) { if (attribute_id.is_named() && names.add(attribute_id.name())) { this->attributes_.append({attribute_id.name(), meta_data.domain, meta_data.data_type}); @@ -241,21 +241,21 @@ GeometryValueLog::GeometryValueLog(const GeometrySet &geometry_set, bool log_ful case GEO_COMPONENT_TYPE_MESH: { const MeshComponent &mesh_component = *(const MeshComponent *)component; MeshInfo &info = this->mesh_info.emplace(); - info.verts_num = mesh_component.attribute_domain_num(ATTR_DOMAIN_POINT); - info.edges_num = mesh_component.attribute_domain_num(ATTR_DOMAIN_EDGE); - info.faces_num = mesh_component.attribute_domain_num(ATTR_DOMAIN_FACE); + info.verts_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT); + info.edges_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_EDGE); + info.faces_num = mesh_component.attribute_domain_size(ATTR_DOMAIN_FACE); break; } case GEO_COMPONENT_TYPE_CURVE: { const CurveComponent &curve_component = *(const CurveComponent *)component; CurveInfo &info = this->curve_info.emplace(); - info.splines_num = curve_component.attribute_domain_num(ATTR_DOMAIN_CURVE); + info.splines_num = curve_component.attribute_domain_size(ATTR_DOMAIN_CURVE); break; } case GEO_COMPONENT_TYPE_POINT_CLOUD: { const PointCloudComponent &pointcloud_component = *(const PointCloudComponent *)component; PointCloudInfo &info = this->pointcloud_info.emplace(); - info.points_num = pointcloud_component.attribute_domain_num(ATTR_DOMAIN_POINT); + info.points_num = pointcloud_component.attribute_domain_size(ATTR_DOMAIN_POINT); break; } case GEO_COMPONENT_TYPE_INSTANCES: { |