[Bf-blender-cvs] [d397ecae325] master: Geometry Nodes: Add a selection input to the store named attribute node
Charlie Jolly
noreply at git.blender.org
Tue Jan 10 19:16:48 CET 2023
Commit: d397ecae3255a150954bee32249fd7d58a39d903
Author: Charlie Jolly
Date: Sat Jan 7 14:32:49 2023 +0000
Branches: master
https://developer.blender.org/rBd397ecae3255a150954bee32249fd7d58a39d903
Geometry Nodes: Add a selection input to the store named attribute node
This patch is a response to T101313.
Adds a selection to the Store Named Attribute node.
If the attribute does not exist unselected parts
are filled with zero values. Otherwise, only the
selected parts are filled.
Differential Revision: https://developer.blender.org/D16237
===================================================================
M source/blender/blenkernel/BKE_geometry_fields.hh
M source/blender/blenkernel/intern/geometry_fields.cc
M source/blender/nodes/geometry/nodes/node_geo_store_named_attribute.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_geometry_fields.hh b/source/blender/blenkernel/BKE_geometry_fields.hh
index 085bade618c..5f5333beb63 100644
--- a/source/blender/blenkernel/BKE_geometry_fields.hh
+++ b/source/blender/blenkernel/BKE_geometry_fields.hh
@@ -315,6 +315,12 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
const eAttrDomain domain,
const fn::GField &field);
+bool try_capture_field_on_geometry(GeometryComponent &component,
+ const AttributeIDRef &attribute_id,
+ const eAttrDomain domain,
+ const fn::Field<bool> &selection,
+ const fn::GField &field);
+
/**
* Try to find the geometry domain that the field should be evaluated on. If it is not obvious
* which domain is correct, none is returned.
diff --git a/source/blender/blenkernel/intern/geometry_fields.cc b/source/blender/blenkernel/intern/geometry_fields.cc
index 9c691cb5870..f4f4d0d8719 100644
--- a/source/blender/blenkernel/intern/geometry_fields.cc
+++ b/source/blender/blenkernel/intern/geometry_fields.cc
@@ -1,5 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
+
#include "BKE_attribute.hh"
#include "BKE_curves.hh"
#include "BKE_geometry_fields.hh"
@@ -408,6 +410,7 @@ bool NormalFieldInput::is_equal_to(const fn::FieldNode &other) const
bool try_capture_field_on_geometry(GeometryComponent &component,
const AttributeIDRef &attribute_id,
const eAttrDomain domain,
+ const fn::Field<bool> &selection,
const fn::GField &field)
{
MutableAttributeAccessor attributes = *component.attributes_for_write();
@@ -423,19 +426,44 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
const IndexMask mask{IndexMask(domain_size)};
const bke::AttributeValidator validator = attributes.lookup_validator(attribute_id);
+ const std::optional<AttributeMetaData> meta_data = attributes.lookup_meta_data(attribute_id);
+ const bool attribute_exists = meta_data && meta_data->domain == domain &&
+ meta_data->data_type == data_type;
+
+ /* We are writing to an attribute that exists already with the correct domain and type. */
+ if (attribute_exists) {
+ if (GSpanAttributeWriter dst_attribute = attributes.lookup_for_write_span(attribute_id)) {
+ bke::GeometryFieldContext field_context{component, domain};
+ const IndexMask mask{IndexMask(domain_size)};
+
+ fn::FieldEvaluator evaluator{field_context, &mask};
+ evaluator.add(validator.validate_field_if_necessary(field));
+ evaluator.set_selection(selection);
+ evaluator.evaluate();
+
+ const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
+
+ array_utils::copy(evaluator.get_evaluated(0), selection, dst_attribute.span);
+
+ dst_attribute.finish();
+ return true;
+ }
+ }
+
/* Could avoid allocating a new buffer if:
- * - We are writing to an attribute that exists already with the correct domain and type.
* - The field does not depend on that attribute (we can't easily check for that yet). */
- void *buffer = MEM_mallocN(type.size() * domain_size, __func__);
-
+ void *buffer = MEM_mallocN_aligned(type.size() * domain_size, type.alignment(), __func__);
+ if (selection.node().depends_on_input() || !fn::evaluate_constant_field(selection)) {
+ /* If every element might not be selected, the buffer must be initialized. */
+ type.value_initialize_n(buffer, domain_size);
+ }
fn::FieldEvaluator evaluator{field_context, &mask};
evaluator.add_with_destination(validator.validate_field_if_necessary(field),
GMutableSpan{type, buffer, domain_size});
+ evaluator.set_selection(selection);
evaluator.evaluate();
- const std::optional<AttributeMetaData> meta_data = attributes.lookup_meta_data(attribute_id);
-
- if (meta_data && meta_data->domain == domain && meta_data->data_type == data_type) {
+ if (attribute_exists) {
if (GAttributeWriter attribute = attributes.lookup_for_write(attribute_id)) {
attribute.varray.set_all(buffer);
attribute.finish();
@@ -457,6 +485,15 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
return false;
}
+bool try_capture_field_on_geometry(GeometryComponent &component,
+ const AttributeIDRef &attribute_id,
+ const eAttrDomain domain,
+ const fn::GField &field)
+{
+ const fn::Field<bool> selection = fn::make_constant_field<bool>(true);
+ return try_capture_field_on_geometry(component, attribute_id, domain, selection, field);
+}
+
std::optional<eAttrDomain> try_detect_field_domain(const GeometryComponent &component,
const fn::GField &field)
{
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 d42793d474f..462b332568f 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
@@ -20,6 +20,7 @@ NODE_STORAGE_FUNCS(NodeGeometryStoreNamedAttribute)
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
+ b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().field_on_all();
b.add_input<decl::String>(N_("Name")).is_attribute_name();
b.add_input<decl::Vector>(N_("Value"), "Value_Vector").field_on_all();
b.add_input<decl::Float>(N_("Value"), "Value_Float").field_on_all();
@@ -52,7 +53,7 @@ static void node_update(bNodeTree *ntree, bNode *node)
const eCustomDataType data_type = eCustomDataType(storage.data_type);
bNodeSocket *socket_geometry = static_cast<bNodeSocket *>(node->inputs.first);
- bNodeSocket *socket_name = socket_geometry->next;
+ bNodeSocket *socket_name = socket_geometry->next->next;
bNodeSocket *socket_vector = socket_name->next;
bNodeSocket *socket_float = socket_vector->next;
bNodeSocket *socket_color4f = socket_float->next;
@@ -108,6 +109,8 @@ static void node_geo_exec(GeoNodeExecParams params)
const eCustomDataType data_type = eCustomDataType(storage.data_type);
const eAttrDomain domain = eAttrDomain(storage.domain);
+ const Field<bool> selection = params.extract_input<Field<bool>>("Selection");
+
GField field;
switch (data_type) {
case CD_PROP_FLOAT:
@@ -147,7 +150,7 @@ static void node_geo_exec(GeoNodeExecParams params)
if (geometry_set.has_instances()) {
GeometryComponent &component = geometry_set.get_component_for_write(
GEO_COMPONENT_TYPE_INSTANCES);
- if (!bke::try_capture_field_on_geometry(component, name, domain, field)) {
+ if (!bke::try_capture_field_on_geometry(component, name, domain, selection, field)) {
if (component.attribute_domain_size(domain) != 0) {
failure.store(true);
}
@@ -160,7 +163,7 @@ static void node_geo_exec(GeoNodeExecParams params)
{GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE}) {
if (geometry_set.has(type)) {
GeometryComponent &component = geometry_set.get_component_for_write(type);
- if (!bke::try_capture_field_on_geometry(component, name, domain, field)) {
+ if (!bke::try_capture_field_on_geometry(component, name, domain, selection, field)) {
if (component.attribute_domain_size(domain) != 0) {
failure.store(true);
}
More information about the Bf-blender-cvs
mailing list