Blender V4.3
node_geo_store_named_attribute.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 <atomic>
6
7#include "UI_interface.hh"
8#include "UI_resources.hh"
9
10#include "RNA_access.hh"
11#include "RNA_enum_types.hh"
12
13#include "BKE_instances.hh"
14#include "BKE_mesh.hh"
16
17#include "NOD_rna_define.hh"
19
20#include "RNA_enum_types.hh"
21
22#include "node_geometry_util.hh"
23
24#include <fmt/format.h>
25
27
29
31{
32 const bNode *node = b.node_or_null();
33
34 b.add_input<decl::Geometry>("Geometry");
35 b.add_input<decl::Bool>("Selection").default_value(true).hide_value().field_on_all();
36 b.add_input<decl::String>("Name").is_attribute_name().hide_label();
37
38 if (node != nullptr) {
39 const NodeGeometryStoreNamedAttribute &storage = node_storage(*node);
40 const eCustomDataType data_type = eCustomDataType(storage.data_type);
41 b.add_input(data_type, "Value").field_on_all();
42 }
43
44 b.add_output<decl::Geometry>("Geometry").propagate_all();
45}
46
47static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
48{
49 uiLayoutSetPropSep(layout, true);
50 uiLayoutSetPropDecorate(layout, false);
51 uiItemR(layout, ptr, "data_type", UI_ITEM_NONE, "", ICON_NONE);
52 uiItemR(layout, ptr, "domain", UI_ITEM_NONE, "", ICON_NONE);
53}
54
55static void node_init(bNodeTree * /*tree*/, bNode *node)
56{
57 NodeGeometryStoreNamedAttribute *data = MEM_cnew<NodeGeometryStoreNamedAttribute>(__func__);
58 data->data_type = CD_PROP_FLOAT;
59 data->domain = int8_t(AttrDomain::Point);
60 node->storage = data;
61}
62
64{
65 const NodeDeclaration &declaration = *params.node_type().static_declaration;
68
69 if (params.in_out() == SOCK_IN) {
70 const std::optional<eCustomDataType> type = bke::socket_type_to_custom_data_type(
71 eNodeSocketDatatype(params.other_socket().type));
72 if (type && *type != CD_PROP_STRING) {
73 /* The input and output sockets have the same name. */
74 params.add_item(IFACE_("Value"), [type](LinkSearchOpParams &params) {
75 bNode &node = params.add_node("GeometryNodeStoreNamedAttribute");
76 node_storage(node).data_type = *type;
77 params.update_and_connect_available_socket(node, "Value");
78 });
79 }
80 }
81}
82
84{
85 GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
86 const std::string name = params.extract_input<std::string>("Name");
87
88 if (name.empty()) {
89 params.set_output("Geometry", std::move(geometry_set));
90 return;
91 }
93 params.error_message_add(NodeWarningType::Info, TIP_(bke::no_procedural_access_message));
94 params.set_output("Geometry", std::move(geometry_set));
95 return;
96 }
98 params.error_message_add(NodeWarningType::Info,
99 TIP_("Anonymous attributes can't be created here"));
100 params.set_output("Geometry", std::move(geometry_set));
101 return;
102 }
103
104 params.used_named_attribute(name, NamedAttributeUsage::Write);
105
106 const NodeGeometryStoreNamedAttribute &storage = node_storage(params.node());
107 const eCustomDataType data_type = eCustomDataType(storage.data_type);
108 const AttrDomain domain = AttrDomain(storage.domain);
109
110 const Field<bool> selection = params.extract_input<Field<bool>>("Selection");
111
112 GField field = params.extract_input<GField>("Value");
115 std::move(field), *bke::custom_data_type_to_cpp_type(data_type));
116 }
117
118 std::atomic<bool> failure = false;
119
120 /* Run on the instances component separately to only affect the top level of instances. */
121 if (domain == AttrDomain::Instance) {
122 if (geometry_set.has_instances()) {
123 GeometryComponent &component = geometry_set.get_component_for_write(
125
126 if (name == "position" && data_type == CD_PROP_FLOAT3) {
127 /* Special case for "position" which is no longer an attribute on instances. */
128 bke::Instances &instances = *geometry_set.get_instances_for_write();
129 bke::InstancesFieldContext context(instances);
130 fn::FieldEvaluator evaluator{context, instances.instances_num()};
131 evaluator.set_selection(selection);
132 evaluator.add_with_destination(field, bke::instance_position_varray_for_write(instances));
133 evaluator.evaluate();
134 }
135 else {
136 if (!bke::try_capture_field_on_geometry(component, name, domain, selection, field)) {
137 if (component.attribute_domain_size(domain) != 0) {
138 failure.store(true);
139 }
140 }
141 }
142 }
143 }
144 else {
145 geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
150 {
151 if (geometry_set.has(type)) {
152 GeometryComponent &component = geometry_set.get_component_for_write(type);
153 if (bke::try_capture_field_on_geometry(component, name, domain, selection, field)) {
154 if (component.type() == GeometryComponent::Type::Mesh) {
155 Mesh &mesh = *geometry_set.get_mesh_for_write();
156 bke::mesh_ensure_default_color_attribute_on_add(mesh, name, domain, data_type);
157 }
158 }
159 else if (component.attribute_domain_size(domain) != 0) {
160 failure.store(true);
161 }
162 }
163 }
164 });
165 }
166
167 if (failure) {
168 const char *domain_name = nullptr;
170 const char *type_name = nullptr;
172 const std::string message = fmt::format(
173 TIP_("Failed to write to attribute \"{}\" with domain \"{}\" and type \"{}\""),
174 name,
175 TIP_(domain_name),
176 TIP_(type_name));
177 params.error_message_add(NodeWarningType::Warning, message);
178 }
179
180 params.set_output("Geometry", std::move(geometry_set));
181}
182
183static void node_rna(StructRNA *srna)
184{
186 srna,
187 "data_type",
188 "Data Type",
189 "Type of data stored in attribute",
193 [](bContext * /*C*/, PointerRNA * /*ptr*/, PropertyRNA * /*prop*/, bool *r_free) {
194 *r_free = true;
197 });
198
200 "domain",
201 "Domain",
202 "Which domain to store the data in",
205 int(AttrDomain::Point));
206}
207
208static void node_register()
209{
210 static blender::bke::bNodeType ntype;
211
213 &ntype, GEO_NODE_STORE_NAMED_ATTRIBUTE, "Store Named Attribute", NODE_CLASS_ATTRIBUTE);
215 "NodeGeometryStoreNamedAttribute",
218 blender::bke::node_type_size(&ntype, 140, 100, 700);
219 ntype.initfunc = node_init;
220 ntype.declare = node_declare;
225
226 node_rna(ntype.rna_ext.srna);
227}
229
230} // namespace blender::nodes::node_geo_store_named_attribute_cc
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1799
#define NODE_CLASS_ATTRIBUTE
Definition BKE_node.hh:419
#define ELEM(...)
#define TIP_(msgid)
#define IFACE_(msgid)
@ CD_PROP_BYTE_COLOR
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_FLOAT2
@ CD_PROP_STRING
@ SOCK_IN
eNodeSocketDatatype
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_storage_enum_accessors(member)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
GVArray try_convert(GVArray varray, const CPPType &to_type) const
int attribute_domain_size(AttrDomain domain) const
void set_selection(Field< bool > selection)
Definition FN_field.hh:385
Vector< SocketDeclaration * > inputs
Vector< SocketDeclaration * > outputs
local_group_size(16, 16) .push_constant(Type b
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
bool attribute_name_is_anonymous(const StringRef name)
const DataTypeConversions & get_implicit_type_conversions()
bool allow_procedural_attribute_access(StringRef attribute_name)
const char * no_procedural_access_message
void mesh_ensure_default_color_attribute_on_add(Mesh &mesh, StringRef id, AttrDomain domain, eCustomDataType data_type)
bool try_capture_field_on_geometry(MutableAttributeAccessor attributes, const fn::FieldContext &field_context, const StringRef attribute_id, AttrDomain domain, const fn::Field< bool > &selection, const fn::GField &field)
void node_type_size(bNodeType *ntype, int width, int minwidth, int maxwidth)
Definition node.cc:4602
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
const CPPType * custom_data_type_to_cpp_type(eCustomDataType type)
VMutableArray< float3 > instance_position_varray_for_write(Instances &instances)
Definition instances.cc:530
std::optional< eCustomDataType > socket_type_to_custom_data_type(eNodeSocketDatatype type)
Definition node.cc:4379
bool generic_attribute_type_supported(const EnumPropertyItem &item)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
void search_link_ops_for_declarations(GatherLinkSearchOpParams &params, Span< SocketDeclaration * > declarations)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
const EnumPropertyItem * enum_items_filter(const EnumPropertyItem *original_item_array, FunctionRef< bool(const EnumPropertyItem &item)> fn)
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
bool RNA_enum_name_from_value(const EnumPropertyItem *item, int value, const char **r_name)
const EnumPropertyItem rna_enum_attribute_domain_items[]
const EnumPropertyItem rna_enum_attribute_type_items[]
signed char int8_t
Definition stdint.h:75
StructRNA * srna
Definition RNA_types.hh:780
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
Instances * get_instances_for_write()
bool has(const GeometryComponent::Type component_type) const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
Defines a node type.
Definition BKE_node.hh:218
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:339
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:363
NodeDeclareFunction declare
Definition BKE_node.hh:347
PointerRNA * ptr
Definition wm_files.cc:4126