[Bf-blender-cvs] [0d3a33e45eb] master: Geometry Nodes: Add "Exists" output to Named Attribute input node

Hans Goudey noreply at git.blender.org
Thu Nov 17 00:28:24 CET 2022


Commit: 0d3a33e45eb3a69b665429cd24694d2d2ca0cbd4
Author: Hans Goudey
Date:   Wed Nov 16 17:27:28 2022 -0600
Branches: master
https://developer.blender.org/rB0d3a33e45eb3a69b665429cd24694d2d2ca0cbd4

Geometry Nodes: Add "Exists" output to Named Attribute input node

As described in T100004, add an output socket that returns true if the
attribute accessed by the node was already present in that context.

Initial patch by Edward (@edward88).

Differential Revision: https://developer.blender.org/D16316

===================================================================

M	source/blender/editors/space_node/node_geometry_attribute_search.cc
M	source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc

===================================================================

diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc
index a1a8fd0dfdc..002faffd0fb 100644
--- a/source/blender/editors/space_node/node_geometry_attribute_search.cc
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -197,10 +197,14 @@ static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
       /* Relink all node links to the newly active output socket. */
       bNodeSocket *output_socket = bke::node_find_enabled_output_socket(*node, "Attribute");
       LISTBASE_FOREACH (bNodeLink *, link, &node_tree->links) {
-        if (link->fromnode == node) {
-          link->fromsock = output_socket;
-          BKE_ntree_update_tag_link_changed(node_tree);
+        if (link->fromnode != node) {
+          continue;
         }
+        if (!STREQ(link->fromsock->name, "Attribute")) {
+          continue;
+        }
+        link->fromsock = output_socket;
+        BKE_ntree_update_tag_link_changed(node_tree);
       }
     }
     BKE_ntree_update_tag_node_property(node_tree, node);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc
index 9d1f90ba0f3..90e7f58c07e 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_named_attribute.cc
@@ -20,6 +20,8 @@ static void node_declare(NodeDeclarationBuilder &b)
   b.add_output<decl::Color>(N_("Attribute"), "Attribute_Color").field_source();
   b.add_output<decl::Bool>(N_("Attribute"), "Attribute_Bool").field_source();
   b.add_output<decl::Int>(N_("Attribute"), "Attribute_Int").field_source();
+
+  b.add_output<decl::Bool>(N_("Exists")).field_source();
 }
 
 static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@@ -57,20 +59,52 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
   const NodeDeclaration &declaration = *params.node_type().fixed_declaration;
   search_link_ops_for_declarations(params, declaration.inputs());
 
+  const bNodeType &node_type = params.node_type();
   if (params.in_out() == SOCK_OUT) {
     const std::optional<eCustomDataType> type = node_data_type_to_custom_data_type(
         eNodeSocketDatatype(params.other_socket().type));
     if (type && *type != CD_PROP_STRING) {
       /* The input and output sockets have the same name. */
-      params.add_item(IFACE_("Attribute"), [type](LinkSearchOpParams &params) {
-        bNode &node = params.add_node("GeometryNodeInputNamedAttribute");
+      params.add_item(IFACE_("Attribute"), [node_type, type](LinkSearchOpParams &params) {
+        bNode &node = params.add_node(node_type);
         node_storage(node).data_type = *type;
         params.update_and_connect_available_socket(node, "Attribute");
       });
+      params.add_item(IFACE_("Exists"), [node_type](LinkSearchOpParams &params) {
+        bNode &node = params.add_node(node_type);
+        params.update_and_connect_available_socket(node, "Exists");
+      });
     }
   }
 }
 
+class AttributeExistsFieldInput final : public bke::GeometryFieldInput {
+ private:
+  std::string name_;
+
+ public:
+  AttributeExistsFieldInput(std::string name, const CPPType &type)
+      : GeometryFieldInput(type, name), name_(std::move(name))
+  {
+    category_ = Category::Generated;
+  }
+
+  static Field<bool> Create(std::string name)
+  {
+    const CPPType &type = CPPType::get<bool>();
+    auto field_input = std::make_shared<AttributeExistsFieldInput>(std::move(name), type);
+    return Field<bool>(field_input);
+  }
+
+  GVArray get_varray_for_context(const bke::GeometryFieldContext &context,
+                                 const IndexMask /*mask*/) const final
+  {
+    const bool exists = context.attributes()->contains(name_);
+    const int domain_size = context.attributes()->domain_size(context.domain());
+    return VArray<bool>::ForSingle(exists, domain_size);
+  }
+};
+
 static void node_geo_exec(GeoNodeExecParams params)
 {
   const NodeGeometryInputNamedAttribute &storage = node_storage(params.node());
@@ -92,24 +126,25 @@ static void node_geo_exec(GeoNodeExecParams params)
 
   switch (data_type) {
     case CD_PROP_FLOAT:
-      params.set_output("Attribute_Float", AttributeFieldInput::Create<float>(std::move(name)));
+      params.set_output("Attribute_Float", AttributeFieldInput::Create<float>(name));
       break;
     case CD_PROP_FLOAT3:
-      params.set_output("Attribute_Vector", AttributeFieldInput::Create<float3>(std::move(name)));
+      params.set_output("Attribute_Vector", AttributeFieldInput::Create<float3>(name));
       break;
     case CD_PROP_COLOR:
-      params.set_output("Attribute_Color",
-                        AttributeFieldInput::Create<ColorGeometry4f>(std::move(name)));
+      params.set_output("Attribute_Color", AttributeFieldInput::Create<ColorGeometry4f>(name));
       break;
     case CD_PROP_BOOL:
-      params.set_output("Attribute_Bool", AttributeFieldInput::Create<bool>(std::move(name)));
+      params.set_output("Attribute_Bool", AttributeFieldInput::Create<bool>(name));
       break;
     case CD_PROP_INT32:
-      params.set_output("Attribute_Int", AttributeFieldInput::Create<int>(std::move(name)));
+      params.set_output("Attribute_Int", AttributeFieldInput::Create<int>(name));
       break;
     default:
       break;
   }
+
+  params.set_output("Exists", AttributeExistsFieldInput::Create(std::move(name)));
 }
 
 }  // namespace blender::nodes::node_geo_input_named_attribute_cc



More information about the Bf-blender-cvs mailing list