Blender  V3.3
node_geo_edge_paths_to_selection.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BKE_attribute_math.hh"
4 #include "BKE_mesh.h"
5 
6 #include "BLI_map.hh"
7 #include "BLI_set.hh"
8 #include "BLI_task.hh"
9 
10 #include "DNA_mesh_types.h"
11 #include "DNA_meshdata_types.h"
12 
13 #include "node_geometry_util.hh"
14 
15 #include <set>
16 
18 
20 {
21  b.add_input<decl::Bool>(N_("Start Vertices")).default_value(true).hide_value().supports_field();
22  b.add_input<decl::Int>(N_("Next Vertex Index")).default_value(-1).hide_value().supports_field();
23  b.add_output<decl::Bool>(N_("Selection")).field_source();
24 }
25 
26 static void edge_paths_to_selection(const Mesh &src_mesh,
27  const IndexMask start_selection,
28  const Span<int> next_indices,
29  MutableSpan<bool> r_selection)
30 {
31  Array<bool> selection(src_mesh.totvert, false);
32 
33  for (const int start_vert : start_selection) {
34  selection[start_vert] = true;
35  }
36 
37  for (const int start_i : start_selection) {
38  int iter = start_i;
39  while (iter != next_indices[iter] && !selection[next_indices[iter]]) {
40  if (next_indices[iter] < 0 || next_indices[iter] >= src_mesh.totvert) {
41  break;
42  }
43  selection[next_indices[iter]] = true;
44  iter = next_indices[iter];
45  }
46  }
47 
48  for (const int i : IndexRange(src_mesh.totedge)) {
49  const MEdge &edge = src_mesh.medge[i];
50  if ((selection[edge.v1] && selection[edge.v2]) &&
51  (edge.v1 == next_indices[edge.v2] || edge.v2 == next_indices[edge.v1])) {
52  r_selection[i] = true;
53  }
54  }
55 }
56 
58  private:
59  Field<bool> start_vertices_;
60  Field<int> next_vertex_;
61 
62  public:
64  : GeometryFieldInput(CPPType::get<bool>(), "Edge Selection"),
65  start_vertices_(start_vertices),
66  next_vertex_(next_vertex)
67  {
69  }
70 
72  const eAttrDomain domain,
73  [[maybe_unused]] IndexMask mask) const final
74  {
75  if (component.type() != GEO_COMPONENT_TYPE_MESH) {
76  return {};
77  }
78 
79  const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
80  const Mesh *mesh = mesh_component.get_for_read();
81  if (mesh == nullptr) {
82  return {};
83  }
84 
87  evaluator.add(next_vertex_);
88  evaluator.add(start_vertices_);
89  evaluator.evaluate();
90  const VArraySpan<int> next_vert = evaluator.get_evaluated<int>(0);
91  const IndexMask start_verts = evaluator.get_evaluated_as_mask(1);
92 
93  if (start_verts.is_empty()) {
94  return {};
95  }
96 
97  Array<bool> selection(mesh->totedge, false);
98  MutableSpan<bool> selection_span = selection.as_mutable_span();
99 
100  edge_paths_to_selection(*mesh, start_verts, next_vert, selection_span);
101 
102  return mesh_component.attributes()->adapt_domain<bool>(
103  VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_EDGE, domain);
104  }
105 
106  uint64_t hash() const override
107  {
108  return get_default_hash_2(start_vertices_, next_vertex_);
109  }
110 
111  bool is_equal_to(const fn::FieldNode &other) const override
112  {
113  if (const PathToEdgeSelectionFieldInput *other_field =
114  dynamic_cast<const PathToEdgeSelectionFieldInput *>(&other)) {
115  return other_field->start_vertices_ == start_vertices_ &&
116  other_field->next_vertex_ == next_vertex_;
117  }
118  return false;
119  }
120 };
121 
123 {
124  Field<bool> start_vertices = 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_vertices, next_vertex)};
128  params.set_output("Selection", std::move(selection_field));
129 }
130 
131 } // namespace blender::nodes::node_geo_edge_paths_to_selection_cc
132 
134 {
136 
137  static bNodeType ntype;
138 
140  &ntype, GEO_NODE_EDGE_PATHS_TO_SELECTION, "Edge Paths to Selection", NODE_CLASS_INPUT);
142  node_type_size(&ntype, 150, 100, 300);
144  nodeRegisterType(&ntype);
145 }
eAttrDomain
Definition: BKE_attribute.h:25
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
@ ATTR_DOMAIN_EDGE
Definition: BKE_attribute.h:28
@ GEO_COMPONENT_TYPE_MESH
#define GEO_NODE_EDGE_PATHS_TO_SELECTION
Definition: BKE_node.h:1511
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
Definition: node.cc:4396
#define NODE_CLASS_INPUT
Definition: BKE_node.h:345
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define final(a, b, c)
Definition: BLI_hash.h:21
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
int attribute_domain_size(eAttrDomain domain) const
Definition: geometry_set.cc:63
const Mesh * get_for_read() const
std::optional< blender::bke::AttributeAccessor > attributes() const final
MutableSpan< T > as_mutable_span()
Definition: BLI_array.hh:236
static VArray ForContainer(ContainerT container)
GVArray get_varray_for_context(const GeometryComponent &component, const eAttrDomain domain, [[maybe_unused]] IndexMask mask) const final
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static void edge_paths_to_selection(const Mesh &src_mesh, const IndexMask start_selection, const Span< int > next_indices, MutableSpan< bool > r_selection)
uint64_t get_default_hash_2(const T1 &v1, const T2 &v2)
Definition: BLI_hash.hh:223
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void register_node_type_geo_edge_paths_to_selection()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
unsigned __int64 uint64_t
Definition: stdint.h:90
struct MEdge * medge
int totedge
int totvert
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)