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(N_("Attribute"), "Attribute_Color").field_source(); b.add_output(N_("Attribute"), "Attribute_Bool").field_source(); b.add_output(N_("Attribute"), "Attribute_Int").field_source(); + + b.add_output(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 ¶ms) 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 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 ¶ms) { - bNode &node = params.add_node("GeometryNodeInputNamedAttribute"); + params.add_item(IFACE_("Attribute"), [node_type, type](LinkSearchOpParams ¶ms) { + 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 ¶ms) { + 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 Create(std::string name) + { + const CPPType &type = CPPType::get(); + auto field_input = std::make_shared(std::move(name), type); + return Field(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::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(std::move(name))); + params.set_output("Attribute_Float", AttributeFieldInput::Create(name)); break; case CD_PROP_FLOAT3: - params.set_output("Attribute_Vector", AttributeFieldInput::Create(std::move(name))); + params.set_output("Attribute_Vector", AttributeFieldInput::Create(name)); break; case CD_PROP_COLOR: - params.set_output("Attribute_Color", - AttributeFieldInput::Create(std::move(name))); + params.set_output("Attribute_Color", AttributeFieldInput::Create(name)); break; case CD_PROP_BOOL: - params.set_output("Attribute_Bool", AttributeFieldInput::Create(std::move(name))); + params.set_output("Attribute_Bool", AttributeFieldInput::Create(name)); break; case CD_PROP_INT32: - params.set_output("Attribute_Int", AttributeFieldInput::Create(std::move(name))); + params.set_output("Attribute_Int", AttributeFieldInput::Create(name)); break; default: break; } + + params.set_output("Exists", AttributeExistsFieldInput::Create(std::move(name))); } } // namespace blender::nodes::node_geo_input_named_attribute_cc