Blender V4.3
node_geo_edge_paths_to_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 "BKE_mesh.hh"
6
7#include "BLI_map.hh"
8#include "BLI_set.hh"
9#include "BLI_task.hh"
10
11#include "node_geometry_util.hh"
12
13#include <set>
14
16
18{
19 b.add_input<decl::Bool>("Start Vertices").default_value(true).hide_value().supports_field();
20 b.add_input<decl::Int>("Next Vertex Index").default_value(-1).hide_value().supports_field();
21 b.add_output<decl::Bool>("Selection").field_source_reference_all();
22}
23
24static void edge_paths_to_selection(const Mesh &src_mesh,
25 const IndexMask &start_selection,
26 const Span<int> next_indices,
27 MutableSpan<bool> r_edge_selection)
28{
29 Array<bool> vert_selection(src_mesh.verts_num, false);
30
31 const IndexRange vert_range(src_mesh.verts_num);
32 start_selection.foreach_index(GrainSize(2048), [&](const int start_vert) {
33 /* If vertex is selected, all next is already selected too. */
34 for (int current_vert = start_vert; !vert_selection[current_vert];
35 current_vert = next_indices[current_vert])
36 {
37 if (UNLIKELY(!vert_range.contains(current_vert))) {
38 break;
39 }
40 vert_selection[current_vert] = true;
41 }
42 });
43
44 const Span<int2> edges = src_mesh.edges();
45 threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
46 for (const int i : range) {
47 const int2 edge = edges[i];
48 if (!(vert_selection[edge[0]] && vert_selection[edge[1]])) {
49 continue;
50 }
51 if (edge[0] == next_indices[edge[1]] || edge[1] == next_indices[edge[0]]) {
52 r_edge_selection[i] = true;
53 }
54 }
55 });
56}
57
59 private:
60 Field<bool> start_vertices_;
61 Field<int> next_vertex_;
62
63 public:
65 : bke::MeshFieldInput(CPPType::get<bool>(), "Edge Selection"),
66 start_vertices_(start_verts),
67 next_vertex_(next_vertex)
68 {
69 category_ = Category::Generated;
70 }
71
73 const AttrDomain domain,
74 const IndexMask & /*mask*/) const final
75 {
76 const bke::MeshFieldContext context{mesh, AttrDomain::Point};
77 fn::FieldEvaluator evaluator{context, mesh.verts_num};
78 evaluator.add(next_vertex_);
79 evaluator.add(start_vertices_);
80 evaluator.evaluate();
81 const VArraySpan<int> next_vert = evaluator.get_evaluated<int>(0);
82 const IndexMask start_verts = evaluator.get_evaluated_as_mask(1);
83 if (start_verts.is_empty()) {
84 return {};
85 }
86
87 Array<bool> selection(mesh.edges_num, false);
88 edge_paths_to_selection(mesh, start_verts, next_vert, selection);
89
90 return mesh.attributes().adapt_domain<bool>(
91 VArray<bool>::ForContainer(std::move(selection)), AttrDomain::Edge, domain);
92 }
93
94 void for_each_field_input_recursive(FunctionRef<void(const FieldInput &)> fn) const override
95 {
96 start_vertices_.node().for_each_field_input_recursive(fn);
97 next_vertex_.node().for_each_field_input_recursive(fn);
98 }
99
100 uint64_t hash() const override
101 {
102 return get_default_hash(start_vertices_, next_vertex_);
103 }
104
105 bool is_equal_to(const fn::FieldNode &other) const override
106 {
107 if (const PathToEdgeSelectionFieldInput *other_field =
108 dynamic_cast<const PathToEdgeSelectionFieldInput *>(&other))
109 {
110 return other_field->start_vertices_ == start_vertices_ &&
111 other_field->next_vertex_ == next_vertex_;
112 }
113 return false;
114 }
115
116 std::optional<AttrDomain> preferred_domain(const Mesh & /*mesh*/) const override
117 {
118 return AttrDomain::Edge;
119 }
120};
121
123{
124 Field<bool> start_verts = params.extract_input<Field<bool>>("Start Vertices");
125 Field<int> next_vertex = params.extract_input<Field<int>>("Next Vertex Index");
126 Field<bool> selection_field{
127 std::make_shared<PathToEdgeSelectionFieldInput>(start_verts, next_vertex)};
128 params.set_output("Selection", std::move(selection_field));
129}
130
131static void node_register()
132{
133 static blender::bke::bNodeType ntype;
134
136 &ntype, GEO_NODE_EDGE_PATHS_TO_SELECTION, "Edge Paths to Selection", NODE_CLASS_INPUT);
137 ntype.declare = node_declare;
138 blender::bke::node_type_size(&ntype, 150, 100, 300);
141}
142NOD_REGISTER_NODE(node_register)
143
144} // namespace blender::nodes::node_geo_edge_paths_to_selection_cc
#define NODE_CLASS_INPUT
Definition BKE_node.hh:404
#define UNLIKELY(x)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
constexpr bool contains(int64_t value) const
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
void foreach_index(Fn &&fn) const
GVArray get_varray_for_context(const Mesh &mesh, const AttrDomain domain, const IndexMask &) const final
void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) const override
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_type_size(bNodeType *ntype, int width, int minwidth, int maxwidth)
Definition node.cc:4602
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
static void edge_paths_to_selection(const Mesh &src_mesh, const IndexMask &start_selection, const Span< int > next_indices, MutableSpan< bool > r_edge_selection)
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
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[]
unsigned __int64 uint64_t
Definition stdint.h:90
int verts_num
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