Blender V4.3
node_geo_material_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
6
7#include "DNA_mesh_types.h"
8
9#include "BLI_task.hh"
10
11#include "BKE_curves.hh"
12#include "BKE_grease_pencil.hh"
13
15
17{
18 b.add_input<decl::Material>("Material").hide_label(true);
19 b.add_output<decl::Bool>("Selection").field_source();
20}
21
23 const Material *material,
24 const AttributeAccessor &attributes,
25 const AttrDomain domain,
26 const IndexMask &domain_mask)
27{
28 const int domain_size = attributes.domain_size(domain);
29 Vector<int> slots;
30 for (const int slot_i : materials.index_range()) {
31 if (materials[slot_i] == material) {
32 slots.append(slot_i);
33 }
34 }
35 if (slots.is_empty()) {
36 return VArray<bool>::ForSingle(false, domain_size);
37 }
38
39 const VArray<int> material_indices = *attributes.lookup_or_default<int>(
40 "material_index", domain, 0);
41 if (const std::optional<int> single = material_indices.get_if_single()) {
42 return VArray<bool>::ForSingle(slots.contains(*single), domain_size);
43 }
44
45 const VArraySpan<int> material_indices_span(material_indices);
46 Array<bool> domain_selection(domain_mask.min_array_size());
47 domain_mask.foreach_index_optimized<int>(GrainSize(1024), [&](const int domain_index) {
48 const int slot_i = material_indices_span[domain_index];
49 domain_selection[domain_index] = slots.contains(slot_i);
50 });
51 return VArray<bool>::ForContainer(std::move(domain_selection));
52}
53
55 Material *material_;
56
57 public:
59 : bke::GeometryFieldInput(CPPType::get<bool>(), "Material Selection node"),
60 material_(material)
61 {
63 }
64
66 const IndexMask &mask) const final
67 {
68 switch (context.type()) {
70 const Mesh *mesh = context.mesh();
71 if (!mesh) {
72 return {};
73 }
74 const AttrDomain domain = context.domain();
75 const IndexMask domain_mask = (domain == AttrDomain::Face) ? mask :
76 IndexMask(mesh->faces_num);
77 const AttributeAccessor attributes = mesh->attributes();
79 {mesh->mat, mesh->totcol}, material_, attributes, AttrDomain::Face, domain_mask);
80 return attributes.adapt_domain<bool>(std::move(selection), AttrDomain::Face, domain);
81 }
83 const bke::CurvesGeometry *curves = context.curves_or_strokes();
84 if (!curves) {
85 return {};
86 }
87 const AttrDomain domain = context.domain();
88 const IndexMask domain_mask = (domain == AttrDomain::Curve) ?
89 mask :
90 IndexMask(curves->curves_num());
91 const AttributeAccessor attributes = curves->attributes();
92 const VArray<int> material_indices = *attributes.lookup_or_default<int>(
93 "material_index", AttrDomain::Curve, 0);
94 const GreasePencil &grease_pencil = *context.grease_pencil();
96 {grease_pencil.material_array, grease_pencil.material_array_num},
97 material_,
98 attributes,
99 AttrDomain::Curve,
100 domain_mask);
101 return attributes.adapt_domain<bool>(std::move(selection), AttrDomain::Curve, domain);
102 }
104 const Curves *curves_id = context.curves_id();
105 if (!curves_id) {
106 return {};
107 }
108 const bke::CurvesGeometry *curves = context.curves_or_strokes();
109 if (!curves) {
110 return {};
111 }
112 const AttrDomain domain = context.domain();
113 const IndexMask domain_mask = (domain == AttrDomain::Curve) ?
114 mask :
115 IndexMask(curves->curves_num());
116 const AttributeAccessor attributes = curves->attributes();
117 const VArray<int> material_indices = *attributes.lookup_or_default<int>(
118 "material_index", AttrDomain::Curve, 0);
119 VArray<bool> selection = select_by_material({curves_id->mat, curves_id->totcol},
120 material_,
121 attributes,
122 AttrDomain::Curve,
123 domain_mask);
124 return attributes.adapt_domain<bool>(std::move(selection), AttrDomain::Curve, domain);
125 }
126 default:
127 return {};
128 }
129 }
130
131 uint64_t hash() const override
132 {
133 return get_default_hash(material_);
134 }
135
136 bool is_equal_to(const fn::FieldNode &other) const override
137 {
138 if (const MaterialSelectionFieldInput *other_material_selection =
139 dynamic_cast<const MaterialSelectionFieldInput *>(&other))
140 {
141 return material_ == other_material_selection->material_;
142 }
143 return false;
144 }
145
146 std::optional<AttrDomain> preferred_domain(
147 const GeometryComponent & /*component*/) const override
148 {
149 return AttrDomain::Face;
150 }
151};
152
154{
155 Material *material = params.extract_input<Material *>("Material");
156 Field<bool> material_field{std::make_shared<MaterialSelectionFieldInput>(material)};
157 params.set_output("Selection", std::move(material_field));
158}
159
160static void node_register()
161{
162 static blender::bke::bNodeType ntype;
163
165 &ntype, GEO_NODE_MATERIAL_SELECTION, "Material Selection", NODE_CLASS_GEOMETRY);
166 ntype.declare = node_declare;
169}
171
172} // namespace blender::nodes::node_geo_material_selection_cc
Low-level operations for curves.
Low-level operations for grease pencil.
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:418
#define NOD_REGISTER_NODE(REGISTER_FUNC)
std::optional< T > get_if_single() const
static VArray ForContainer(ContainerT container)
static VArray ForSingle(T value, const int64_t size)
bool contains(const T &value) const
void append(const T &value)
bool is_empty() const
void foreach_index_optimized(Fn &&fn) const
std::optional< AttrDomain > preferred_domain(const GeometryComponent &) const override
GVArray get_varray_for_context(const bke::GeometryFieldContext &context, const IndexMask &mask) 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
static VArray< bool > select_by_material(const Span< Material * > materials, const Material *material, const AttributeAccessor &attributes, const AttrDomain domain, const IndexMask &domain_mask)
static void node_declare(NodeDeclarationBuilder &b)
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)
unsigned __int64 uint64_t
Definition stdint.h:90
struct Material ** mat
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