diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index ea7c40f1178..5210ecb7515 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -540,6 +540,7 @@ class NODE_MT_category_GEO_UTILITIES_FIELD(Menu): node_add_menu.add_node_type(layout, "GeometryNodeAccumulateField") node_add_menu.add_node_type(layout, "GeometryNodeFieldAtIndex") node_add_menu.add_node_type(layout, "GeometryNodeFieldOnDomain") + node_add_menu.add_node_type(layout, "GeometryNodeSelectByComponent") node_add_menu.draw_assets_for_catalog(layout, self.bl_label) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 4cce5f6a262..feee300b04d 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1310,6 +1310,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define GEO_NODE_INPUT_SIGNED_DISTANCE 2102 #define GEO_NODE_SAMPLE_VOLUME 2103 #define GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_EDGE 2104 +#define GEO_NODE_SELECT_BY_COMPONENT 2105 /** \} */ diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 8970b6b9b33..20075f5bc1d 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -407,6 +407,7 @@ DefNode(GeometryNode, GEO_NODE_SAMPLE_UV_SURFACE, def_geo_sample_uv_surface, "SA DefNode(GeometryNode, GEO_NODE_SAMPLE_VOLUME, def_geo_sample_volume, "SAMPLE_VOLUME", SampleVolume, "Sample Volume", "Calculate the interpolated values of a Volume grid at the specified position") DefNode(GeometryNode, GEO_NODE_SCALE_ELEMENTS, def_geo_scale_elements, "SCALE_ELEMENTS", ScaleElements, "Scale Elements", "Scale groups of connected edges and faces") DefNode(GeometryNode, GEO_NODE_SCALE_INSTANCES, 0, "SCALE_INSTANCES", ScaleInstances, "Scale Instances", "Scale geometry instances in local or global space") +DefNode(GeometryNode, GEO_NODE_SELECT_BY_COMPONENT, 0, "SELECT_BY_COMPONENT", SelectByComponent, "Select by Component", "Find the type of the currently evaluated geometry") DefNode(GeometryNode, GEO_NODE_SDF_VOLUME_SPHERE, 0, "SDF_VOLUME_SPHERE", SDFVolumeSphere, "SDF Volume Sphere", "Generate an SDF Volume Sphere") DefNode(GeometryNode, GEO_NODE_SELF_OBJECT, 0, "SELF_OBJECT", SelfObject, "Self Object", "Retrieve the object that contains the geometry nodes modifier currently being executed") DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS",SeparateComponents, "Separate Components", "Split a geometry into a separate output for each type of data in the geometry") diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 4dcb9a3d20d..d017626c159 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -159,6 +159,7 @@ set(SRC nodes/node_geo_sample_volume.cc nodes/node_geo_scale_elements.cc nodes/node_geo_scale_instances.cc + nodes/node_geo_select_by_component.cc nodes/node_geo_sdf_volume_sphere.cc nodes/node_geo_self_object.cc nodes/node_geo_separate_components.cc diff --git a/source/blender/nodes/geometry/node_geometry_register.cc b/source/blender/nodes/geometry/node_geometry_register.cc index 97c24f39a10..08a4fbf780c 100644 --- a/source/blender/nodes/geometry/node_geometry_register.cc +++ b/source/blender/nodes/geometry/node_geometry_register.cc @@ -143,6 +143,7 @@ void register_geometry_nodes() register_node_type_geo_sample_volume(); register_node_type_geo_scale_elements(); register_node_type_geo_scale_instances(); + register_node_type_geo_select_by_component(); register_node_type_geo_sdf_volume_sphere(); register_node_type_geo_self_object(); register_node_type_geo_separate_components(); diff --git a/source/blender/nodes/geometry/node_geometry_register.hh b/source/blender/nodes/geometry/node_geometry_register.hh index 879d181343a..dcee7c53392 100644 --- a/source/blender/nodes/geometry/node_geometry_register.hh +++ b/source/blender/nodes/geometry/node_geometry_register.hh @@ -140,6 +140,7 @@ void register_node_type_geo_sample_uv_surface(); void register_node_type_geo_sample_volume(); void register_node_type_geo_scale_elements(); void register_node_type_geo_scale_instances(); +void register_node_type_geo_select_by_component(); void register_node_type_geo_sdf_volume_sphere(); void register_node_type_geo_select_by_handle_type(); void register_node_type_geo_self_object(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_select_by_component.cc b/source/blender/nodes/geometry/nodes/node_geo_select_by_component.cc new file mode 100644 index 00000000000..bb9fe7a0a8c --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_select_by_component.cc @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_geometry_set.h" + +#include "BLI_index_mask.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_select_by_component_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output(N_("Is Mesh")).field_source(); + b.add_output(N_("Is Curves")).field_source(); + b.add_output(N_("Is Point Cloud")).field_source(); + b.add_output(N_("Is Instances")).field_source(); +} + +class SelectByComponentFieldInput final : public bke::GeometryFieldInput { + private: + const GeometryComponentType type_; + + public: + SelectByComponentFieldInput(const GeometryComponentType type) + : bke::GeometryFieldInput(CPPType::get(), "Select by Component"), type_(type) + { + } + + GVArray get_varray_for_context(const bke::GeometryFieldContext &context, + const IndexMask &mask) const final + { + const GeometryComponentType context_component_type = context.type(); + return VArray::ForSingle(context_component_type == type_, mask.size()); + } + + uint64_t hash() const override + { + return uint64_t(type_); + } + + bool is_equal_to(const fn::FieldNode &other) const override + { + if (const SelectByComponentFieldInput *other_mask = + dynamic_cast(&other)) + { + return other_mask->type_ == this->type_; + } + return false; + } +}; + +static void node_geo_exec(GeoNodeExecParams params) +{ + if (params.output_is_required("Is Mesh")) { + params.set_output( + "Is Mesh", + Field{std::make_shared(GEO_COMPONENT_TYPE_MESH)}); + } + if (params.output_is_required("Is Curves")) { + params.set_output( + "Is Curves", + Field{std::make_shared(GEO_COMPONENT_TYPE_CURVE)}); + } + if (params.output_is_required("Is Point Cloud")) { + params.set_output("Is Point Cloud", + Field{std::make_shared( + GEO_COMPONENT_TYPE_POINT_CLOUD)}); + } + if (params.output_is_required("Is Instances")) { + params.set_output( + "Is Instances", + Field{std::make_shared(GEO_COMPONENT_TYPE_INSTANCES)}); + } +} + +} // namespace blender::nodes::node_geo_select_by_component_cc + +void register_node_type_geo_select_by_component() +{ + namespace file_ns = blender::nodes::node_geo_select_by_component_cc; + + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_SELECT_BY_COMPONENT, "Select by Component", NODE_CLASS_CONVERTER); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.declare = file_ns::node_declare; + nodeRegisterType(&ntype); +}