Geometry Nodes: Select by Component node #104602

Open
Iliya Katushenock wants to merge 6 commits from mod_moder/blender:for_component_new into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 95 additions and 0 deletions

View File

@ -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)

View File

@ -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
/** \} */

View File

@ -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")

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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<decl::Bool>(N_("Is Mesh")).field_source();
b.add_output<decl::Bool>(N_("Is Curves")).field_source();
mod_moder marked this conversation as resolved Outdated

I think Is Curves would be more consistent with the current design for namingfor (still have to update other nodes for that though).

I think `Is Curves` would be more consistent with the current design for namingfor (still have to update other nodes for that though).
b.add_output<decl::Bool>(N_("Is Point Cloud")).field_source();
b.add_output<decl::Bool>(N_("Is Instances")).field_source();
}
class SelectByComponentFieldInput final : public bke::GeometryFieldInput {
private:
const GeometryComponentType type_;
public:
SelectByComponentFieldInput(const GeometryComponentType type)
: bke::GeometryFieldInput(CPPType::get<bool>(), "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<bool>::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<const SelectByComponentFieldInput *>(&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<bool>{std::make_shared<SelectByComponentFieldInput>(GEO_COMPONENT_TYPE_MESH)});
}
if (params.output_is_required("Is Curves")) {
params.set_output(
"Is Curves",
Field<bool>{std::make_shared<SelectByComponentFieldInput>(GEO_COMPONENT_TYPE_CURVE)});
}
if (params.output_is_required("Is Point Cloud")) {
params.set_output("Is Point Cloud",
Field<bool>{std::make_shared<SelectByComponentFieldInput>(
GEO_COMPONENT_TYPE_POINT_CLOUD)});
}
if (params.output_is_required("Is Instances")) {
params.set_output(
"Is Instances",
Field<bool>{std::make_shared<SelectByComponentFieldInput>(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);
}