Blender V5.0
node_geo_curve_endpoint_selection.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_task.hh"
6
7#include "BKE_curves.hh"
8
10
12
14{
15 b.add_input<decl::Int>("Start Size")
16 .min(0)
18 .supports_field()
19 .description("The amount of points to select from the start of each spline");
20 b.add_input<decl::Int>("End Size")
21 .min(0)
23 .supports_field()
24 .description("The amount of points to select from the end of each spline");
25 b.add_output<decl::Bool>("Selection")
26 .field_source_reference_all()
27 .description("The selection from the start and end of the splines based on the input sizes");
28}
29
31 Field<int> start_size_;
32 Field<int> end_size_;
33
34 public:
36 : bke::GeometryFieldInput(CPPType::get<bool>(), "Endpoint Selection node"),
37 start_size_(start_size),
38 end_size_(end_size)
39 {
41 }
42
44 const IndexMask & /*mask*/) const final
45 {
46 if (context.domain() != AttrDomain::Point) {
47 return {};
48 }
49 const bke::CurvesGeometry *curves_ptr = context.curves_or_strokes();
50 if (!curves_ptr) {
51 return {};
52 }
53 const bke::CurvesGeometry &curves = *curves_ptr;
54 if (curves.is_empty()) {
55 return {};
56 }
57
58 const bke::GeometryFieldContext sub_context{context, AttrDomain::Curve};
59 fn::FieldEvaluator evaluator{sub_context, curves.curves_num()};
60 evaluator.add(start_size_);
61 evaluator.add(end_size_);
62 evaluator.evaluate();
63 const VArray<int> start_size = evaluator.get_evaluated<int>(0);
64 const VArray<int> end_size = evaluator.get_evaluated<int>(1);
65
66 Array<bool> selection(curves.points_num(), false);
67 MutableSpan<bool> selection_span = selection.as_mutable_span();
68 const OffsetIndices points_by_curve = curves.points_by_curve();
69 devirtualize_varray2(start_size, end_size, [&](const auto start_size, const auto end_size) {
70 threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange curves_range) {
71 for (const int i : curves_range) {
72 const IndexRange points = points_by_curve[i];
73 const int start = std::max(start_size[i], 0);
74 const int end = std::max(end_size[i], 0);
75
76 selection_span.slice(points.take_front(start)).fill(true);
77 selection_span.slice(points.take_back(end)).fill(true);
78 }
79 });
80 });
81
82 return VArray<bool>::from_container(std::move(selection));
83 };
84
86 {
87 start_size_.node().for_each_field_input_recursive(fn);
88 end_size_.node().for_each_field_input_recursive(fn);
89 }
90
92 {
93 return get_default_hash(start_size_, end_size_);
94 }
95
96 bool is_equal_to(const fn::FieldNode &other) const final
97 {
98 if (const EndpointFieldInput *other_endpoint = dynamic_cast<const EndpointFieldInput *>(
99 &other))
100 {
101 return start_size_ == other_endpoint->start_size_ && end_size_ == other_endpoint->end_size_;
102 }
103 return false;
104 }
105
106 std::optional<AttrDomain> preferred_domain(const GeometryComponent & /*component*/) const final
107 {
108 return AttrDomain::Point;
109 }
110};
111
113{
114 Field<int> start_size = params.extract_input<Field<int>>("Start Size");
115 Field<int> end_size = params.extract_input<Field<int>>("End Size");
116 Field<bool> selection_field{std::make_shared<EndpointFieldInput>(start_size, end_size)};
117 params.set_output("Selection", std::move(selection_field));
118}
119
120static void node_register()
121{
122 static blender::bke::bNodeType ntype;
124 &ntype, "GeometryNodeCurveEndpointSelection", GEO_NODE_CURVE_ENDPOINT_SELECTION);
125 ntype.ui_name = "Endpoint Selection";
126 ntype.ui_description = "Provide a selection for an arbitrary number of endpoints in each spline";
127 ntype.enum_name_legacy = "CURVE_ENDPOINT_SELECTION";
128 ntype.nclass = NODE_CLASS_INPUT;
129 ntype.declare = node_declare;
131
133}
134NOD_REGISTER_NODE(node_register)
135
136} // namespace blender::nodes::node_geo_curve_endpoint_selection_cc
Low-level operations for curves.
#define NODE_CLASS_INPUT
Definition BKE_node.hh:447
#define GEO_NODE_CURVE_ENDPOINT_SELECTION
#define final(a, b, c)
Definition BLI_hash.h:19
#define NOD_REGISTER_NODE(REGISTER_FUNC)
unsigned long long int uint64_t
static VArray from_container(ContainerT container)
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
FieldInput(const CPPType &type, std::string debug_name="")
Definition field.cc:677
int add(GField field, GVArray *varray_ptr)
Definition field.cc:751
const GVArray & get_evaluated(const int field_index) const
Definition FN_field.hh:448
std::optional< AttrDomain > preferred_domain(const GeometryComponent &) const final
GVArray get_varray_for_context(const bke::GeometryFieldContext &context, const IndexMask &) const final
void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) const final
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
void devirtualize_varray2(const VArray< T1 > &varray1, const VArray< T2 > &varray2, const Func &func, bool enable=true)
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
#define min(a, b)
Definition sort.cc:36
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:354
const char * enum_name_legacy
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:362