diff options
author | Hans Goudey <h.goudey@me.com> | 2022-03-14 19:48:11 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-03-14 19:48:11 +0300 |
commit | d4e46c13cc92e01489a031a6afe6bafb5af5ca18 (patch) | |
tree | 5c6294d006044d4100500f9e92bce8fea36c8841 /source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc | |
parent | a5578351c38e2b2bb45d940a2fc57354e5fe3a5e (diff) |
Geometry Nodes: Add named attribute nodes behind experimental flag
This commit adds three nodes:
- `Remove Attribute`: Removes an attribute with the given name
- `Named Attribute`: A field input node
- `Store Named Attribute`: Puts results of a field in a named attribute
They are added behind a new experimental feature flag, because further
development of attribute search and name dependency visualization will
happen as separate steps.
Ref T91742
Differential Revision: https://developer.blender.org/D12685
Diffstat (limited to 'source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc')
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc new file mode 100644 index 00000000000..202241affeb --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_remove_attribute.cc @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "node_geometry_util.hh" + +#include "NOD_socket_search_link.hh" + +namespace blender::nodes::node_geo_remove_attribute_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>(N_("Geometry")); + b.add_input<decl::String>(N_("Name")).is_attribute_name(); + b.add_output<decl::Geometry>(N_("Geometry")); +} + +static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) +{ + if (U.experimental.use_named_attribute_nodes == 0) { + return; + } + const NodeDeclaration &declaration = *params.node_type().fixed_declaration; + search_link_ops_for_declarations(params, declaration.inputs()); + search_link_ops_for_declarations(params, declaration.outputs()); +} + +static void node_geo_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + const std::string name = params.extract_input<std::string>("Name"); + if (name.empty() || !U.experimental.use_named_attribute_nodes) { + params.set_output("Geometry", std::move(geometry_set)); + return; + } + + std::atomic<bool> attribute_exists = false; + std::atomic<bool> cannot_delete = false; + + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + for (const GeometryComponentType type : {GEO_COMPONENT_TYPE_MESH, + GEO_COMPONENT_TYPE_POINT_CLOUD, + GEO_COMPONENT_TYPE_CURVE, + GEO_COMPONENT_TYPE_INSTANCES}) { + if (geometry_set.has(type)) { + /* 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)) { + attribute_exists = true; + } + else { + continue; + } + + GeometryComponent &component = geometry_set.get_component_for_write(type); + if (!component.attribute_try_delete(name)) { + cannot_delete = true; + } + } + } + }); + + if (!attribute_exists) { + params.error_message_add(NodeWarningType::Info, + TIP_("Attribute does not exist: \"") + name + "\""); + } + if (cannot_delete) { + params.error_message_add(NodeWarningType::Info, + TIP_("Cannot delete attribute with name \"") + name + "\""); + } + + params.set_output("Geometry", std::move(geometry_set)); +} + +} // namespace blender::nodes::node_geo_remove_attribute_cc + +void register_node_type_geo_remove_attribute() +{ + namespace file_ns = blender::nodes::node_geo_remove_attribute_cc; + + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_REMOVE_ATTRIBUTE, "Remove Attribute", NODE_CLASS_ATTRIBUTE); + ntype.declare = file_ns::node_declare; + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.gather_link_search_ops = file_ns::node_gather_link_searches; + nodeRegisterType(&ntype); +} |