Blender V4.3
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
9#include "UI_resources.hh"
10
11#include "node_geometry_util.hh"
12
14
16{
17 b.add_input<decl::Int>("Start Size")
18 .min(0)
20 .supports_field()
21 .description("The amount of points to select from the start of each spline");
22 b.add_input<decl::Int>("End Size")
23 .min(0)
25 .supports_field()
26 .description("The amount of points to select from the end of each spline");
27 b.add_output<decl::Bool>("Selection")
28 .field_source_reference_all()
29 .description("The selection from the start and end of the splines based on the input sizes");
30}
31
33 Field<int> start_size_;
34 Field<int> end_size_;
35
36 public:
38 : bke::GeometryFieldInput(CPPType::get<bool>(), "Endpoint Selection node"),
39 start_size_(start_size),
40 end_size_(end_size)
41 {
43 }
44
46 const IndexMask & /*mask*/) const final
47 {
48 if (context.domain() != AttrDomain::Point) {
49 return {};
50 }
51 const bke::CurvesGeometry *curves_ptr = context.curves_or_strokes();
52 if (!curves_ptr) {
53 return {};
54 }
55 const bke::CurvesGeometry &curves = *curves_ptr;
56 if (curves.points_num() == 0) {
57 return {};
58 }
59
60 const bke::GeometryFieldContext sub_context{context, AttrDomain::Curve};
61 fn::FieldEvaluator evaluator{sub_context, curves.curves_num()};
62 evaluator.add(start_size_);
63 evaluator.add(end_size_);
64 evaluator.evaluate();
65 const VArray<int> start_size = evaluator.get_evaluated<int>(0);
66 const VArray<int> end_size = evaluator.get_evaluated<int>(1);
67
68 Array<bool> selection(curves.points_num(), false);
69 MutableSpan<bool> selection_span = selection.as_mutable_span();
70 const OffsetIndices points_by_curve = curves.points_by_curve();
71 devirtualize_varray2(start_size, end_size, [&](const auto start_size, const auto end_size) {
72 threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange curves_range) {
73 for (const int i : curves_range) {
74 const IndexRange points = points_by_curve[i];
75 const int start = std::max(start_size[i], 0);
76 const int end = std::max(end_size[i], 0);
77
78 selection_span.slice(points.take_front(start)).fill(true);
79 selection_span.slice(points.take_back(end)).fill(true);
80 }
81 });
82 });
83
84 return VArray<bool>::ForContainer(std::move(selection));
85 };
86
87 void for_each_field_input_recursive(FunctionRef<void(const FieldInput &)> fn) const final
88 {
89 start_size_.node().for_each_field_input_recursive(fn);
91 }
92
93 uint64_t hash() const final
94 {
95 return get_default_hash(start_size_, end_size_);
96 }
97
98 bool is_equal_to(const fn::FieldNode &other) const final
99 {
100 if (const EndpointFieldInput *other_endpoint = dynamic_cast<const EndpointFieldInput *>(
101 &other))
102 {
103 return start_size_ == other_endpoint->start_size_ && end_size_ == other_endpoint->end_size_;
104 }
105 return false;
106 }
107
108 std::optional<AttrDomain> preferred_domain(const GeometryComponent & /*component*/) const final
109 {
110 return AttrDomain::Point;
111 }
112};
113
115{
116 Field<int> start_size = params.extract_input<Field<int>>("Start Size");
117 Field<int> end_size = params.extract_input<Field<int>>("End Size");
118 Field<bool> selection_field{std::make_shared<EndpointFieldInput>(start_size, end_size)};
119 params.set_output("Selection", std::move(selection_field));
120}
121
122static void node_register()
123{
124 static blender::bke::bNodeType ntype;
125
127 &ntype, GEO_NODE_CURVE_ENDPOINT_SELECTION, "Endpoint Selection", NODE_CLASS_INPUT);
128 ntype.declare = node_declare;
130
132}
133NOD_REGISTER_NODE(node_register)
134
135} // namespace blender::nodes::node_geo_curve_endpoint_selection_cc
Low-level operations for curves.
#define NODE_CLASS_INPUT
Definition BKE_node.hh:404
#define NOD_REGISTER_NODE(REGISTER_FUNC)
static VArray ForContainer(ContainerT container)
int add(GField field, GVArray *varray_ptr)
Definition field.cc:756
virtual void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) const
Definition field.cc:587
const FieldNode & node() const
Definition FN_field.hh:137
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
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
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:95
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)
Definition BLI_hash.hh:219
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
#define min(a, b)
Definition sort.c:32
unsigned __int64 uint64_t
Definition stdint.h:90
Defines a node type.
Definition BKE_node.hh:218
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:339
NodeDeclareFunction declare
Definition BKE_node.hh:347