Blender V4.3
geometry_nodes_execute.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
8
9#include "BLI_math_color.hh"
10#include "BLI_math_euler.hh"
12#include "BLI_string.h"
13
14#include "NOD_geometry.hh"
18#include "NOD_socket.hh"
19
22#include "BKE_geometry_set.hh"
23#include "BKE_idprop.hh"
24#include "BKE_lib_id.hh"
25#include "BKE_node_enum.hh"
26#include "BKE_node_runtime.hh"
29
31
32#include "UI_resources.hh"
33
36
37namespace blender::nodes {
38
39static void add_used_ids_from_sockets(const ListBase &sockets, Set<ID *> &ids)
40{
41 LISTBASE_FOREACH (const bNodeSocket *, socket, &sockets) {
42 switch (socket->type) {
43 case SOCK_OBJECT: {
44 if (Object *object = ((bNodeSocketValueObject *)socket->default_value)->value) {
45 ids.add(reinterpret_cast<ID *>(object));
46 }
47 break;
48 }
49 case SOCK_COLLECTION: {
50 if (Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value)
51 {
52 ids.add(reinterpret_cast<ID *>(collection));
53 }
54 break;
55 }
56 case SOCK_MATERIAL: {
57 if (Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value) {
58 ids.add(reinterpret_cast<ID *>(material));
59 }
60 break;
61 }
62 case SOCK_TEXTURE: {
63 if (Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value) {
64 ids.add(reinterpret_cast<ID *>(texture));
65 }
66 break;
67 }
68 case SOCK_IMAGE: {
69 if (Image *image = ((bNodeSocketValueImage *)socket->default_value)->value) {
70 ids.add(reinterpret_cast<ID *>(image));
71 }
72 break;
73 }
74 }
75 }
76}
77
85{
86 if (node.type == GEO_NODE_COLLECTION_INFO) {
87 const NodeGeometryCollectionInfo &storage = *static_cast<const NodeGeometryCollectionInfo *>(
88 node.storage);
90 }
91
92 if (node.type == GEO_NODE_OBJECT_INFO) {
93 const NodeGeometryObjectInfo &storage = *static_cast<const NodeGeometryObjectInfo *>(
94 node.storage);
96 }
97 if (node.type == GEO_NODE_SELF_OBJECT) {
98 return true;
99 }
101 return true;
102 }
103
104 return false;
105}
106
108 Set<ID *> &ids,
109 bool &r_needs_own_transform_relation,
110 bool &r_needs_scene_camera_relation,
111 Set<const bNodeTree *> &checked_groups)
112{
113 if (!checked_groups.add(&tree)) {
114 return;
115 }
116
117 tree.ensure_topology_cache();
118 for (const bNode *node : tree.all_nodes()) {
119 add_used_ids_from_sockets(node->inputs, ids);
120 add_used_ids_from_sockets(node->outputs, ids);
121 r_needs_own_transform_relation |= node_needs_own_transform_relation(*node);
122 r_needs_scene_camera_relation |= (node->type == GEO_NODE_INPUT_ACTIVE_CAMERA);
123 }
124
125 for (const bNode *node : tree.group_nodes()) {
126 if (const bNodeTree *sub_tree = reinterpret_cast<const bNodeTree *>(node->id)) {
128 ids,
129 r_needs_own_transform_relation,
130 r_needs_scene_camera_relation,
131 checked_groups);
132 }
133 }
134}
135
137 Set<ID *> &r_ids,
138 bool &r_needs_own_transform_relation,
139 bool &r_needs_scene_camera_relation)
140{
141 Set<const bNodeTree *> checked_groups;
143 tree, r_ids, r_needs_own_transform_relation, r_needs_scene_camera_relation, checked_groups);
144}
145
147{
148 return "_use_attribute";
149}
150
152{
153 return "_attribute_name";
154}
155
160
161bool input_has_attribute_toggle(const bNodeTree &node_tree, const int socket_index)
162{
163 node_tree.ensure_interface_cache();
164 const bke::bNodeSocketType *typeinfo =
165 node_tree.interface_inputs()[socket_index]->socket_typeinfo();
166 if (ELEM(typeinfo->type, SOCK_MENU)) {
167 return false;
168 }
169
170 BLI_assert(node_tree.runtime->field_inferencing_interface);
171 const nodes::FieldInferencingInterface &field_interface =
172 *node_tree.runtime->field_inferencing_interface;
173 return field_interface.inputs[socket_index] != nodes::InputSocketFieldType::None;
174}
175
177 IDPropertyUIDataInt *ui_data)
178{
179 int idprop_items_num = 0;
180 IDPropertyUIDataEnumItem *idprop_items = nullptr;
181
182 if (value->enum_items && !value->enum_items->items.is_empty()) {
183 const Span<bke::RuntimeNodeEnumItem> items = value->enum_items->items;
184 idprop_items_num = items.size();
185 idprop_items = MEM_cnew_array<IDPropertyUIDataEnumItem>(items.size(), __func__);
186 for (const int i : items.index_range()) {
187 const bke::RuntimeNodeEnumItem &item = items[i];
188 IDPropertyUIDataEnumItem &idprop_item = idprop_items[i];
189 idprop_item.value = item.identifier;
190 /* TODO: The name may not be unique!
191 * We require a unique identifier string for IDProperty and RNA enums,
192 * so node enums should probably have this too. */
193 idprop_item.identifier = BLI_strdup_null(item.name.c_str());
194 idprop_item.name = BLI_strdup_null(item.name.c_str());
195 idprop_item.description = BLI_strdup_null(item.description.c_str());
196 idprop_item.icon = ICON_NONE;
197 }
198 }
199
200 /* Fallback: if no items are defined, use a dummy item so the id property is not shown as a plain
201 * int value. */
202 if (idprop_items_num == 0) {
203 idprop_items_num = 1;
204 idprop_items = MEM_cnew_array<IDPropertyUIDataEnumItem>(1, __func__);
205 idprop_items->value = 0;
206 idprop_items->identifier = BLI_strdup("DUMMY");
207 idprop_items->name = BLI_strdup("");
208 idprop_items->description = BLI_strdup("");
209 idprop_items->icon = ICON_NONE;
210 }
211
212 /* Node enum definitions should already be valid. */
213 BLI_assert(IDP_EnumItemsValidate(idprop_items, idprop_items_num, nullptr));
214 ui_data->enum_items = idprop_items;
215 ui_data->enum_items_num = idprop_items_num;
216}
217
218static std::unique_ptr<IDProperty, bke::idprop::IDPropertyDeleter> id_name_or_value_prop(
219 const StringRefNull identifier,
220 ID *id,
221 const std::optional<ID_Type> id_type,
222 const bool use_name_for_ids)
223{
224 if (use_name_for_ids) {
225 return bke::idprop::create(identifier, id ? id->name + 2 : "");
226 }
227 auto prop = bke::idprop::create(identifier, id);
228 if (id_type) {
230 ui_data->id_type = *id_type;
231 }
232 return prop;
233}
234
235std::unique_ptr<IDProperty, bke::idprop::IDPropertyDeleter> id_property_create_from_socket(
236 const bNodeTreeInterfaceSocket &socket, const bool use_name_for_ids)
237{
238 const StringRefNull identifier = socket.identifier;
239 const bke::bNodeSocketType *typeinfo = socket.socket_typeinfo();
240 const eNodeSocketDatatype type = typeinfo ? eNodeSocketDatatype(typeinfo->type) : SOCK_CUSTOM;
241 switch (type) {
242 case SOCK_FLOAT: {
243 const bNodeSocketValueFloat *value = static_cast<const bNodeSocketValueFloat *>(
244 socket.socket_data);
245 auto property = bke::idprop::create(identifier, value->value);
247 ui_data->base.rna_subtype = value->subtype;
248 ui_data->soft_min = double(value->min);
249 ui_data->soft_max = double(value->max);
250 ui_data->default_value = value->value;
251 return property;
252 }
253 case SOCK_INT: {
254 const bNodeSocketValueInt *value = static_cast<const bNodeSocketValueInt *>(
255 socket.socket_data);
256 auto property = bke::idprop::create(identifier, value->value);
257 IDPropertyUIDataInt *ui_data = (IDPropertyUIDataInt *)IDP_ui_data_ensure(property.get());
258 ui_data->base.rna_subtype = value->subtype;
259 ui_data->soft_min = value->min;
260 ui_data->soft_max = value->max;
261 ui_data->default_value = value->value;
262 return property;
263 }
264 case SOCK_VECTOR: {
265 const bNodeSocketValueVector *value = static_cast<const bNodeSocketValueVector *>(
266 socket.socket_data);
267 auto property = bke::idprop::create(
268 identifier, Span<float>{value->value[0], value->value[1], value->value[2]});
270 ui_data->base.rna_subtype = value->subtype;
271 ui_data->soft_min = double(value->min);
272 ui_data->soft_max = double(value->max);
273 ui_data->default_array = (double *)MEM_mallocN(sizeof(double[3]), "mod_prop_default");
274 ui_data->default_array_len = 3;
275 for (const int i : IndexRange(3)) {
276 ui_data->default_array[i] = double(value->value[i]);
277 }
278 return property;
279 }
280 case SOCK_RGBA: {
281 const bNodeSocketValueRGBA *value = static_cast<const bNodeSocketValueRGBA *>(
282 socket.socket_data);
283 auto property = bke::idprop::create(
284 identifier,
285 Span<float>{value->value[0], value->value[1], value->value[2], value->value[3]});
287 ui_data->base.rna_subtype = PROP_COLOR;
288 ui_data->default_array = (double *)MEM_mallocN(sizeof(double[4]), __func__);
289 ui_data->default_array_len = 4;
290 ui_data->min = 0.0;
291 ui_data->max = FLT_MAX;
292 ui_data->soft_min = 0.0;
293 ui_data->soft_max = 1.0;
294 for (const int i : IndexRange(4)) {
295 ui_data->default_array[i] = double(value->value[i]);
296 }
297 return property;
298 }
299 case SOCK_BOOLEAN: {
300 if (is_layer_selection_field(socket)) {
301 /* We can't use the value from the socket here since it doesn't storing a string. */
302 return bke::idprop::create(identifier, "");
303 }
304 const bNodeSocketValueBoolean *value = static_cast<const bNodeSocketValueBoolean *>(
305 socket.socket_data);
306 auto property = bke::idprop::create_bool(identifier, value->value);
308 ui_data->default_value = value->value != 0;
309 return property;
310 }
311 case SOCK_ROTATION: {
312 const bNodeSocketValueRotation *value = static_cast<const bNodeSocketValueRotation *>(
313 socket.socket_data);
314 auto property = bke::idprop::create(
315 identifier,
316 Span<float>{value->value_euler[0], value->value_euler[1], value->value_euler[2]});
317 IDPropertyUIDataFloat *ui_data = reinterpret_cast<IDPropertyUIDataFloat *>(
318 IDP_ui_data_ensure(property.get()));
319 ui_data->base.rna_subtype = PROP_EULER;
320 return property;
321 }
322 case SOCK_STRING: {
323 const bNodeSocketValueString *value = static_cast<const bNodeSocketValueString *>(
324 socket.socket_data);
325 auto property = bke::idprop::create(identifier, value->value);
327 property.get());
328 ui_data->default_value = BLI_strdup(value->value);
329 ui_data->base.rna_subtype = value->subtype;
330 return property;
331 }
332 case SOCK_MENU: {
333 const bNodeSocketValueMenu *value = static_cast<const bNodeSocketValueMenu *>(
334 socket.socket_data);
335 auto property = bke::idprop::create(identifier, value->value);
336 IDPropertyUIDataInt *ui_data = (IDPropertyUIDataInt *)IDP_ui_data_ensure(property.get());
337 id_property_int_update_enum_items(value, ui_data);
338 return property;
339 }
340 case SOCK_OBJECT: {
341 const bNodeSocketValueObject *value = static_cast<const bNodeSocketValueObject *>(
342 socket.socket_data);
343 ID *id = reinterpret_cast<ID *>(value->value);
344 auto property = id_name_or_value_prop(identifier, id, ID_OB, use_name_for_ids);
345 return property;
346 }
347 case SOCK_COLLECTION: {
348 const bNodeSocketValueCollection *value = static_cast<const bNodeSocketValueCollection *>(
349 socket.socket_data);
350 ID *id = reinterpret_cast<ID *>(value->value);
351 return id_name_or_value_prop(identifier, id, std::nullopt, use_name_for_ids);
352 }
353 case SOCK_TEXTURE: {
354 const bNodeSocketValueTexture *value = static_cast<const bNodeSocketValueTexture *>(
355 socket.socket_data);
356 ID *id = reinterpret_cast<ID *>(value->value);
357 return id_name_or_value_prop(identifier, id, std::nullopt, use_name_for_ids);
358 }
359 case SOCK_IMAGE: {
360 const bNodeSocketValueImage *value = static_cast<const bNodeSocketValueImage *>(
361 socket.socket_data);
362 ID *id = reinterpret_cast<ID *>(value->value);
363 return id_name_or_value_prop(identifier, id, std::nullopt, use_name_for_ids);
364 }
365 case SOCK_MATERIAL: {
366 const bNodeSocketValueMaterial *value = static_cast<const bNodeSocketValueMaterial *>(
367 socket.socket_data);
368 ID *id = reinterpret_cast<ID *>(value->value);
369 return id_name_or_value_prop(identifier, id, std::nullopt, use_name_for_ids);
370 }
371 case SOCK_MATRIX:
372 case SOCK_CUSTOM:
373 case SOCK_GEOMETRY:
374 case SOCK_SHADER:
375 return nullptr;
376 }
377 return nullptr;
378}
379
381 IDProperty *new_property)
382{
383 if (old_property.type != IDP_INT) {
384 return false;
385 }
386 if (new_property) {
387 BLI_assert(new_property->type == IDP_INT);
388 IDP_Int(new_property) = IDP_Int(&old_property);
389 }
390 return true;
391}
392
394 const IDProperty &old_property, IDProperty *new_property, const int len)
395{
396 if (!(old_property.type == IDP_ARRAY &&
397 ELEM(old_property.subtype, IDP_INT, IDP_FLOAT, IDP_DOUBLE) && old_property.len == len))
398 {
399 return false;
400 }
401
402 if (new_property) {
403 BLI_assert(new_property->type == IDP_ARRAY && new_property->subtype == IDP_FLOAT &&
404 new_property->len == len);
405
406 switch (old_property.subtype) {
407 case IDP_DOUBLE: {
408 double *const old_value = static_cast<double *const>(IDP_Array(&old_property));
409 float *new_value = static_cast<float *>(new_property->data.pointer);
410 for (int i = 0; i < len; i++) {
411 new_value[i] = float(old_value[i]);
412 }
413 break;
414 }
415 case IDP_INT: {
416 int *const old_value = static_cast<int *const>(IDP_Array(&old_property));
417 float *new_value = static_cast<float *>(new_property->data.pointer);
418 for (int i = 0; i < len; i++) {
419 new_value[i] = float(old_value[i]);
420 }
421 break;
422 }
423 case IDP_FLOAT: {
424 float *const old_value = static_cast<float *const>(IDP_Array(&old_property));
425 memcpy(new_property->data.pointer, old_value, sizeof(float) * size_t(len));
426 break;
427 }
428 }
429 }
430 return true;
431}
432
434 const IDProperty &old_property, IDProperty *new_property)
435{
436 if (old_property.type != IDP_STRING || old_property.subtype != IDP_STRING_SUB_UTF8) {
437 return false;
438 }
439 if (new_property) {
440 BLI_assert(new_property->type == IDP_STRING && new_property->subtype == IDP_STRING_SUB_UTF8);
441 IDP_AssignString(new_property, IDP_String(&old_property));
442 }
443 return true;
444}
445
455 const bNodeTreeInterfaceSocket &socket,
456 const IDProperty &old_property,
457 IDProperty *new_property,
458 const bool use_name_for_ids)
459{
460 const bke::bNodeSocketType *typeinfo = socket.socket_typeinfo();
461 const eNodeSocketDatatype type = typeinfo ? eNodeSocketDatatype(typeinfo->type) : SOCK_CUSTOM;
462 switch (type) {
463 case SOCK_FLOAT:
464 if (!ELEM(old_property.type, IDP_FLOAT, IDP_INT, IDP_DOUBLE)) {
465 return false;
466 }
467 if (new_property) {
468 BLI_assert(new_property->type == IDP_FLOAT);
469 switch (old_property.type) {
470 case IDP_DOUBLE:
471 IDP_Float(new_property) = float(IDP_Double(&old_property));
472 break;
473 case IDP_INT:
474 IDP_Float(new_property) = float(IDP_Int(&old_property));
475 break;
476 case IDP_FLOAT:
477 IDP_Float(new_property) = IDP_Float(&old_property);
478 break;
479 }
480 }
481 return true;
482 case SOCK_INT:
483 return old_id_property_type_matches_socket_convert_to_new_int(old_property, new_property);
484 case SOCK_VECTOR:
485 case SOCK_ROTATION:
487 old_property, new_property, 3);
488 case SOCK_RGBA:
490 old_property, new_property, 4);
491 case SOCK_BOOLEAN:
492 if (is_layer_selection_field(socket)) {
494 new_property);
495 }
496 if (!ELEM(old_property.type, IDP_BOOLEAN, IDP_INT)) {
497 return false;
498 }
499 /* Exception: Do conversion from old Integer property (for versioning from older data model),
500 * but do not consider int idprop as a valid input for a bool socket. */
501 if (new_property) {
502 BLI_assert(new_property->type == IDP_BOOLEAN);
503 switch (old_property.type) {
504 case IDP_INT:
505 IDP_Bool(new_property) = bool(IDP_Int(&old_property));
506 break;
507 case IDP_BOOLEAN:
508 IDP_Bool(new_property) = IDP_Bool(&old_property);
509 break;
510 }
511 }
512 return old_property.type == IDP_BOOLEAN;
513 case SOCK_STRING:
514 return old_id_property_type_matches_socket_convert_to_new_string(old_property, new_property);
515 case SOCK_MENU:
516 return old_id_property_type_matches_socket_convert_to_new_int(old_property, new_property);
517 case SOCK_OBJECT:
518 case SOCK_COLLECTION:
519 case SOCK_TEXTURE:
520 case SOCK_IMAGE:
521 case SOCK_MATERIAL:
522 if (use_name_for_ids) {
524 new_property);
525 }
526 if (old_property.type != IDP_ID) {
527 return false;
528 }
529 if (new_property) {
530 BLI_assert(new_property->type == IDP_ID);
531 ID *id = IDP_Id(&old_property);
532 new_property->data.pointer = id;
533 id_us_plus(id);
534 }
535 return true;
536 case SOCK_CUSTOM:
537 case SOCK_MATRIX:
538 case SOCK_GEOMETRY:
539 case SOCK_SHADER:
540 return false;
541 }
543 return false;
544}
545
547 const IDProperty &property,
548 const bool use_name_for_ids)
549{
551 socket, property, nullptr, use_name_for_ids);
552}
553
555 const eNodeSocketDatatype socket_value_type,
556 void *r_value)
557{
558 switch (socket_value_type) {
559 case SOCK_FLOAT: {
560 float value = 0.0f;
561 if (property.type == IDP_FLOAT) {
562 value = IDP_Float(&property);
563 }
564 else if (property.type == IDP_DOUBLE) {
565 value = float(IDP_Double(&property));
566 }
567 new (r_value) bke::SocketValueVariant(value);
568 break;
569 }
570 case SOCK_INT: {
571 int value = IDP_Int(&property);
572 new (r_value) bke::SocketValueVariant(value);
573 break;
574 }
575 case SOCK_VECTOR: {
576 const void *property_array = IDP_Array(&property);
577 float3 value;
578 if (property.subtype == IDP_FLOAT) {
579 value = float3(static_cast<const float *>(property_array));
580 }
581 else if (property.subtype == IDP_INT) {
582 value = float3(int3(static_cast<const int *>(property_array)));
583 }
584 else {
585 BLI_assert(property.subtype == IDP_DOUBLE);
586 value = float3(double3(static_cast<const double *>(property_array)));
587 }
588 new (r_value) bke::SocketValueVariant(value);
589 break;
590 }
591 case SOCK_RGBA: {
592 const void *property_array = IDP_Array(&property);
593 float4 vec;
594 if (property.subtype == IDP_FLOAT) {
595 vec = float4(static_cast<const float *>(property_array));
596 }
597 else if (property.subtype == IDP_INT) {
598 vec = float4(int4(static_cast<const int *>(property_array)));
599 }
600 else {
601 BLI_assert(property.subtype == IDP_DOUBLE);
602 vec = float4(double4(static_cast<const double *>(property_array)));
603 }
604 ColorGeometry4f value(vec);
605 new (r_value) bke::SocketValueVariant(value);
606 break;
607 }
608 case SOCK_BOOLEAN: {
609 const bool value = IDP_Bool(&property);
610 new (r_value) bke::SocketValueVariant(value);
611 break;
612 }
613 case SOCK_ROTATION: {
614 const void *property_array = IDP_Array(&property);
615 float3 vec;
616 if (property.subtype == IDP_FLOAT) {
617 vec = float3(static_cast<const float *>(property_array));
618 }
619 else if (property.subtype == IDP_INT) {
620 vec = float3(int3(static_cast<const int *>(property_array)));
621 }
622 else {
623 BLI_assert(property.subtype == IDP_DOUBLE);
624 vec = float3(double3(static_cast<const double *>(property_array)));
625 }
626 const math::EulerXYZ euler_value = math::EulerXYZ(vec);
627 new (r_value) bke::SocketValueVariant(math::to_quaternion(euler_value));
628 break;
629 }
630 case SOCK_STRING: {
631 std::string value = IDP_String(&property);
632 new (r_value) bke::SocketValueVariant(std::move(value));
633 break;
634 }
635 case SOCK_MENU: {
636 int value = IDP_Int(&property);
637 new (r_value) bke::SocketValueVariant(std::move(value));
638 break;
639 }
640 case SOCK_OBJECT: {
641 ID *id = IDP_Id(&property);
642 Object *object = (id && GS(id->name) == ID_OB) ? (Object *)id : nullptr;
643 *(Object **)r_value = object;
644 break;
645 }
646 case SOCK_COLLECTION: {
647 ID *id = IDP_Id(&property);
648 Collection *collection = (id && GS(id->name) == ID_GR) ? (Collection *)id : nullptr;
649 *(Collection **)r_value = collection;
650 break;
651 }
652 case SOCK_TEXTURE: {
653 ID *id = IDP_Id(&property);
654 Tex *texture = (id && GS(id->name) == ID_TE) ? (Tex *)id : nullptr;
655 *(Tex **)r_value = texture;
656 break;
657 }
658 case SOCK_IMAGE: {
659 ID *id = IDP_Id(&property);
660 Image *image = (id && GS(id->name) == ID_IM) ? (Image *)id : nullptr;
661 *(Image **)r_value = image;
662 break;
663 }
664 case SOCK_MATERIAL: {
665 ID *id = IDP_Id(&property);
666 Material *material = (id && GS(id->name) == ID_MA) ? (Material *)id : nullptr;
667 *(Material **)r_value = material;
668 break;
669 }
670 default: {
672 break;
673 }
674 }
675}
676
677std::optional<StringRef> input_attribute_name_get(const IDProperty &props,
678 const bNodeTreeInterfaceSocket &io_input)
679{
680 IDProperty *use_attribute = IDP_GetPropertyFromGroup(
681 &props, (std::string(io_input.identifier) + input_use_attribute_suffix()).c_str());
682 if (!use_attribute) {
683 return std::nullopt;
684 }
685 if (use_attribute->type == IDP_INT) {
686 if (IDP_Int(use_attribute) == 0) {
687 return std::nullopt;
688 }
689 }
690 if (use_attribute->type == IDP_BOOLEAN) {
691 if (!IDP_Bool(use_attribute)) {
692 return std::nullopt;
693 }
694 }
695
696 const IDProperty *property_attribute_name = IDP_GetPropertyFromGroup(
697 &props, (io_input.identifier + input_attribute_name_suffix()).c_str());
698
699 return IDP_String(property_attribute_name);
700}
701
703 const IDProperty *properties,
704 const int input_index,
705 void *r_value)
706{
707 const bNodeTreeInterfaceSocket &io_input = *tree.interface_inputs()[input_index];
708 const bke::bNodeSocketType *typeinfo = io_input.socket_typeinfo();
709 const eNodeSocketDatatype socket_data_type = typeinfo ? eNodeSocketDatatype(typeinfo->type) :
711 if (properties == nullptr) {
712 typeinfo->get_geometry_nodes_cpp_value(io_input.socket_data, r_value);
713 return;
714 }
715 const IDProperty *property = IDP_GetPropertyFromGroup(properties, io_input.identifier);
716 if (property == nullptr) {
717 typeinfo->get_geometry_nodes_cpp_value(io_input.socket_data, r_value);
718 return;
719 }
720 if (!id_property_type_matches_socket(io_input, *property)) {
721 typeinfo->get_geometry_nodes_cpp_value(io_input.socket_data, r_value);
722 return;
723 }
724
725 if (!input_has_attribute_toggle(tree, input_index)) {
726 init_socket_cpp_value_from_property(*property, socket_data_type, r_value);
727 return;
728 }
729
730 const std::optional<StringRef> attribute_name = input_attribute_name_get(*properties, io_input);
731 if (attribute_name && bke::allow_procedural_attribute_access(*attribute_name)) {
732 fn::GField attribute_field = bke::AttributeFieldInput::Create(*attribute_name,
733 *typeinfo->base_cpp_type);
734 new (r_value) bke::SocketValueVariant(std::move(attribute_field));
735 }
736 else if (is_layer_selection_field(io_input)) {
737 const IDProperty *property_layer_name = IDP_GetPropertyFromGroup(properties,
738 io_input.identifier);
739 StringRef layer_name = IDP_String(property_layer_name);
740 const fn::GField selection_field(
741 std::make_shared<bke::NamedLayerSelectionFieldInput>(layer_name), 0);
742 new (r_value) bke::SocketValueVariant(std::move(selection_field));
743 }
744 else {
745 init_socket_cpp_value_from_property(*property, socket_data_type, r_value);
746 }
747}
748
753
760
766 const bNodeTree &tree, const IDProperty *properties, Span<GMutablePointer> output_values)
767{
768 const bNode &output_node = *tree.group_output_node();
770 for (const bNodeSocket *socket : output_node.input_sockets().drop_front(1).drop_back(1)) {
772 continue;
773 }
774
775 const std::string prop_name = socket->identifier + input_attribute_name_suffix();
776 const IDProperty *prop = IDP_GetPropertyFromGroup(properties, prop_name.c_str());
777 if (prop == nullptr) {
778 continue;
779 }
780 const StringRefNull attribute_name = IDP_String(prop);
781 if (attribute_name.is_empty()) {
782 continue;
783 }
784 if (!bke::allow_procedural_attribute_access(attribute_name)) {
785 continue;
786 }
787
788 const int index = socket->index();
789 bke::SocketValueVariant &value_variant = *output_values[index].get<bke::SocketValueVariant>();
790 const fn::GField field = value_variant.get<fn::GField>();
791
792 const bNodeTreeInterfaceSocket *interface_socket = tree.interface_outputs()[index];
793 const bke::AttrDomain domain = bke::AttrDomain(interface_socket->attribute_domain);
794 OutputAttributeInfo output_info;
795 output_info.field = std::move(field);
796 output_info.name = attribute_name;
797 outputs_by_domain.add(domain, std::move(output_info));
798 }
799 return outputs_by_domain;
800}
801
809 const bool do_instances)
810{
811 Vector<OutputAttributeToStore> attributes_to_store;
812 for (const auto component_type : {bke::GeometryComponent::Type::Mesh,
816 {
817 if (!geometry.has(component_type)) {
818 continue;
819 }
820 if (!do_instances && component_type == bke::GeometryComponent::Type::Instance) {
821 continue;
822 }
823 const bke::GeometryComponent &component = *geometry.get_component(component_type);
824 const bke::AttributeAccessor attributes = *component.attributes();
825 for (const auto item : outputs_by_domain.items()) {
826 const bke::AttrDomain domain = item.key;
827 const Span<OutputAttributeInfo> outputs_info = item.value;
828 if (!attributes.domain_supported(domain)) {
829 continue;
830 }
831 const int domain_size = attributes.domain_size(domain);
832 bke::GeometryFieldContext field_context{component, domain};
833 fn::FieldEvaluator field_evaluator{field_context, domain_size};
834 for (const OutputAttributeInfo &output_info : outputs_info) {
835 const CPPType &type = output_info.field.cpp_type();
836 const bke::AttributeValidator validator = attributes.lookup_validator(output_info.name);
837
839 component_type,
840 domain,
841 output_info.name,
843 type,
844 MEM_mallocN_aligned(type.size() * domain_size, type.alignment(), __func__),
845 domain_size}};
846 fn::GField field = validator.validate_field_if_necessary(output_info.field);
847 field_evaluator.add_with_destination(std::move(field), store.data);
848 attributes_to_store.append(store);
849 }
850 field_evaluator.evaluate();
851 }
852 }
853 return attributes_to_store;
854}
855
857 bke::GeometrySet &geometry, const Span<OutputAttributeToStore> attributes_to_store)
858{
859 for (const OutputAttributeToStore &store : attributes_to_store) {
860 bke::GeometryComponent &component = geometry.get_component_for_write(store.component_type);
861 bke::MutableAttributeAccessor attributes = *component.attributes_for_write();
862
863 const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(store.data.type());
864 const std::optional<bke::AttributeMetaData> meta_data = attributes.lookup_meta_data(
865 store.name);
866
867 /* Attempt to remove the attribute if it already exists but the domain and type don't match.
868 * Removing the attribute won't succeed if it is built in and non-removable. */
869 if (meta_data.has_value() &&
870 (meta_data->domain != store.domain || meta_data->data_type != data_type))
871 {
872 attributes.remove(store.name);
873 }
874
875 /* Try to create the attribute reusing the stored buffer. This will only succeed if the
876 * attribute didn't exist before, or if it existed but was removed above. */
877 if (attributes.add(store.name,
878 store.domain,
879 bke::cpp_type_to_custom_data_type(store.data.type()),
880 bke::AttributeInitMoveArray(store.data.data())))
881 {
882 continue;
883 }
884
886 store.name, store.domain, data_type);
887 if (attribute) {
888 attribute.varray.set_all(store.data.data());
889 attribute.finish();
890 }
891
892 /* We were unable to reuse the data, so it must be destructed and freed. */
893 store.data.type().destruct_n(store.data.data(), store.data.size());
894 MEM_freeN(store.data.data());
895 }
896}
897
899 const bNodeTree &tree,
900 const IDProperty *properties,
901 Span<GMutablePointer> output_values)
902{
903 /* All new attribute values have to be computed before the geometry is actually changed. This is
904 * necessary because some fields might depend on attributes that are overwritten. */
906 find_output_attributes_to_store(tree, properties, output_values);
907 if (outputs_by_domain.size() == 0) {
908 return;
909 }
910 const bool only_instance_attributes = outputs_by_domain.size() == 1 &&
911 *outputs_by_domain.keys().begin() ==
913 if (only_instance_attributes) {
914 /* No need to call #modify_geometry_sets when only adding attributes to top-level instances.
915 * This avoids some unnecessary data copies currently if some sub-geometries are not yet owned
916 * by the geometry set, i.e. they use #GeometryOwnershipType::Editable/ReadOnly. */
918 geometry, outputs_by_domain, true);
919 store_computed_output_attributes(geometry, attributes_to_store);
920 return;
921 }
922
923 geometry.modify_geometry_sets([&](bke::GeometrySet &instance_geometry) {
924 /* Instance attributes should only be created for the top-level geometry. */
925 const bool do_instances = &geometry == &instance_geometry;
927 instance_geometry, outputs_by_domain, do_instances);
928 store_computed_output_attributes(instance_geometry, attributes_to_store);
929 });
930}
931
933 const IDProperty *properties,
934 const ComputeContext &base_compute_context,
935 GeoNodesCallData &call_data,
936 bke::GeometrySet input_geometry)
937{
938 const nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info =
940 const GeometryNodesGroupFunction &function = lf_graph_info.function;
941 const lf::LazyFunction &lazy_function = *function.function;
942 const int num_inputs = lazy_function.inputs().size();
943 const int num_outputs = lazy_function.outputs().size();
944
945 Array<GMutablePointer> param_inputs(num_inputs);
946 Array<GMutablePointer> param_outputs(num_outputs);
947 Array<std::optional<lf::ValueUsage>> param_input_usages(num_inputs);
948 Array<lf::ValueUsage> param_output_usages(num_outputs);
949 Array<bool> param_set_outputs(num_outputs, false);
950
951 /* We want to evaluate the main outputs, but don't care about which inputs are used for now. */
952 param_output_usages.as_mutable_span().slice(function.outputs.main).fill(lf::ValueUsage::Used);
953 param_output_usages.as_mutable_span()
954 .slice(function.outputs.input_usages)
956
958 user_data.call_data = &call_data;
959 call_data.root_ntree = &btree;
960
961 user_data.compute_context = &base_compute_context;
962
963 LinearAllocator<> allocator;
964 Vector<GMutablePointer> inputs_to_destruct;
965
966 btree.ensure_interface_cache();
967
968 /* Prepare main inputs. */
969 for (const int i : btree.interface_inputs().index_range()) {
970 const bNodeTreeInterfaceSocket &interface_socket = *btree.interface_inputs()[i];
971 const bke::bNodeSocketType *typeinfo = interface_socket.socket_typeinfo();
972 const eNodeSocketDatatype socket_type = typeinfo ? eNodeSocketDatatype(typeinfo->type) :
974 if (socket_type == SOCK_GEOMETRY && i == 0) {
975 param_inputs[function.inputs.main[0]] = &input_geometry;
976 continue;
977 }
978
979 const CPPType *type = typeinfo->geometry_nodes_cpp_type;
980 BLI_assert(type != nullptr);
981 void *value = allocator.allocate(type->size(), type->alignment());
982 initialize_group_input(btree, properties, i, value);
983 param_inputs[function.inputs.main[i]] = {type, value};
984 inputs_to_destruct.append({type, value});
985 }
986
987 /* Prepare used-outputs inputs. */
988 Array<bool> output_used_inputs(btree.interface_outputs().size(), true);
989 for (const int i : btree.interface_outputs().index_range()) {
990 param_inputs[function.inputs.output_usages[i]] = &output_used_inputs[i];
991 }
992
993 /* No anonymous attributes have to be propagated. */
994 Array<bke::AnonymousAttributeSet> attributes_to_propagate(
996 for (const int i : attributes_to_propagate.index_range()) {
997 param_inputs[function.inputs.attributes_to_propagate.range[i]] = &attributes_to_propagate[i];
998 }
999
1000 /* Prepare memory for output values. */
1001 for (const int i : IndexRange(num_outputs)) {
1002 const lf::Output &lf_output = lazy_function.outputs()[i];
1003 const CPPType &type = *lf_output.type;
1004 void *buffer = allocator.allocate(type.size(), type.alignment());
1005 param_outputs[i] = {type, buffer};
1006 }
1007
1008 nodes::GeoNodesLFLocalUserData local_user_data(user_data);
1009
1010 lf::Context lf_context(lazy_function.init_storage(allocator), &user_data, &local_user_data);
1011 lf::BasicParams lf_params{lazy_function,
1012 param_inputs,
1013 param_outputs,
1014 param_input_usages,
1015 param_output_usages,
1016 param_set_outputs};
1017 {
1018 ScopedComputeContextTimer timer{lf_context};
1019 lazy_function.execute(lf_params, lf_context);
1020 }
1021 lazy_function.destruct_storage(lf_context.storage);
1022
1023 for (GMutablePointer &ptr : inputs_to_destruct) {
1024 ptr.destruct();
1025 }
1026
1027 bke::GeometrySet output_geometry = std::move(*param_outputs[0].get<bke::GeometrySet>());
1028 store_output_attributes(output_geometry, btree, properties, param_outputs);
1029
1030 for (const int i : IndexRange(num_outputs)) {
1031 if (param_set_outputs[i]) {
1032 GMutablePointer &ptr = param_outputs[i];
1033 ptr.destruct();
1034 }
1035 }
1036
1037 return output_geometry;
1038}
1039
1041 const IDProperty *old_properties,
1042 IDProperty &properties,
1043 const bool use_name_for_ids)
1044{
1045 tree.ensure_interface_cache();
1046 const Span<const bNodeTreeInterfaceSocket *> tree_inputs = tree.interface_inputs();
1047 for (const int i : tree_inputs.index_range()) {
1048 const bNodeTreeInterfaceSocket &socket = *tree_inputs[i];
1049 const StringRefNull socket_identifier = socket.identifier;
1050 const bke::bNodeSocketType *typeinfo = socket.socket_typeinfo();
1051 const eNodeSocketDatatype socket_type = typeinfo ? eNodeSocketDatatype(typeinfo->type) :
1053 IDProperty *new_prop =
1054 nodes::id_property_create_from_socket(socket, use_name_for_ids).release();
1055 if (new_prop == nullptr) {
1056 /* Out of the set of supported input sockets, only
1057 * geometry sockets aren't added to the modifier. */
1058 BLI_assert(ELEM(socket_type, SOCK_GEOMETRY, SOCK_MATRIX));
1059 continue;
1060 }
1061
1063 if (socket.description && socket.description[0] != '\0') {
1064 IDPropertyUIData *ui_data = IDP_ui_data_ensure(new_prop);
1065 ui_data->description = BLI_strdup(socket.description);
1066 }
1067 IDP_AddToGroup(&properties, new_prop);
1068
1069 if (old_properties != nullptr) {
1070 const IDProperty *old_prop = IDP_GetPropertyFromGroup(old_properties,
1071 socket_identifier.c_str());
1072 if (old_prop != nullptr) {
1073 /* Re-use the value (and only the value!) from the old property if possible, handling
1074 * conversion to new property's type as needed. */
1076 socket, *old_prop, new_prop, use_name_for_ids);
1077 }
1078 }
1079
1081 const std::string use_attribute_id = socket_identifier + input_use_attribute_suffix();
1082 const std::string attribute_name_id = socket_identifier + input_attribute_name_suffix();
1083
1084 IDProperty *use_attribute_prop = bke::idprop::create_bool(use_attribute_id, false).release();
1085 IDP_AddToGroup(&properties, use_attribute_prop);
1086
1087 IDProperty *attribute_prop = bke::idprop::create(attribute_name_id, "").release();
1088 IDP_AddToGroup(&properties, attribute_prop);
1089
1090 if (old_properties == nullptr) {
1091 if (socket.default_attribute_name && socket.default_attribute_name[0] != '\0') {
1093 IDP_Int(use_attribute_prop) = 1;
1094 }
1095 }
1096 else {
1097 IDProperty *old_prop_use_attribute = IDP_GetPropertyFromGroup(old_properties,
1098 use_attribute_id.c_str());
1099 if (old_prop_use_attribute != nullptr) {
1100 IDP_CopyPropertyContent(use_attribute_prop, old_prop_use_attribute);
1101 }
1102
1103 IDProperty *old_attribute_name_prop = IDP_GetPropertyFromGroup(old_properties,
1104 attribute_name_id.c_str());
1105 if (old_attribute_name_prop != nullptr) {
1106 IDP_CopyPropertyContent(attribute_prop, old_attribute_name_prop);
1107 }
1108 }
1109 }
1110 }
1111}
1112
1114 const IDProperty *old_properties,
1115 IDProperty &properties)
1116{
1117 tree.ensure_topology_cache();
1118 const Span<const bNodeTreeInterfaceSocket *> tree_outputs = tree.interface_outputs();
1119 for (const int i : tree_outputs.index_range()) {
1120 const bNodeTreeInterfaceSocket &socket = *tree_outputs[i];
1121 const StringRefNull socket_identifier = socket.identifier;
1122 const bke::bNodeSocketType *typeinfo = socket.socket_typeinfo();
1123 const eNodeSocketDatatype socket_type = typeinfo ? eNodeSocketDatatype(typeinfo->type) :
1125 if (!nodes::socket_type_has_attribute_toggle(socket_type)) {
1126 continue;
1127 }
1128
1129 const std::string idprop_name = socket_identifier + input_attribute_name_suffix();
1130 IDProperty *new_prop = IDP_NewStringMaxSize("", MAX_NAME, idprop_name.c_str());
1131 if (socket.description && socket.description[0] != '\0') {
1132 IDPropertyUIData *ui_data = IDP_ui_data_ensure(new_prop);
1133 ui_data->description = BLI_strdup(socket.description);
1134 }
1135 IDP_AddToGroup(&properties, new_prop);
1136
1137 if (old_properties == nullptr) {
1138 if (socket.default_attribute_name && socket.default_attribute_name[0] != '\0') {
1140 }
1141 }
1142 else {
1143 IDProperty *old_prop = IDP_GetPropertyFromGroup(old_properties, idprop_name.c_str());
1144 if (old_prop != nullptr) {
1145 /* #IDP_CopyPropertyContent replaces the UI data as well, which we don't (we only
1146 * want to replace the values). So release it temporarily and replace it after. */
1147 IDPropertyUIData *ui_data = new_prop->ui_data;
1148 new_prop->ui_data = nullptr;
1149 IDP_CopyPropertyContent(new_prop, old_prop);
1150 if (new_prop->ui_data != nullptr) {
1151 IDP_ui_data_free(new_prop);
1152 }
1153 new_prop->ui_data = ui_data;
1154 }
1155 }
1156 }
1157}
1158
1159} // namespace blender::nodes
void IDP_ui_data_free(IDProperty *prop)
Definition idprop.cc:1183
#define IDP_Float(prop)
bool IDP_EnumItemsValidate(const IDPropertyUIDataEnumItem *items, int items_num, void(*error_fn)(const char *))
Definition idprop.cc:480
#define IDP_Int(prop)
void IDP_CopyPropertyContent(IDProperty *dst, const IDProperty *src) ATTR_NONNULL()
Definition idprop.cc:866
#define IDP_Id(prop)
#define IDP_Bool(prop)
void IDP_AssignString(IDProperty *prop, const char *st) ATTR_NONNULL()
Definition idprop.cc:431
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:763
void IDP_AssignStringMaxSize(IDProperty *prop, const char *st, size_t st_maxncpy) ATTR_NONNULL()
Definition idprop.cc:413
#define IDP_String(prop)
#define IDP_Double(prop)
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:722
IDProperty * IDP_NewStringMaxSize(const char *st, size_t st_maxncpy, const char *name, eIDPropertyFlag flags={}) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(3)
Definition idprop.cc:357
IDPropertyUIData * IDP_ui_data_ensure(IDProperty *prop)
Definition idprop.cc:1739
#define IDP_Array(prop)
void id_us_plus(ID *id)
Definition lib_id.cc:351
#define GEO_NODE_OBJECT_INFO
Definition BKE_node.hh:1174
#define GEO_NODE_SELF_OBJECT
Definition BKE_node.hh:1302
#define GEO_NODE_DEFORM_CURVES_ON_SURFACE
Definition BKE_node.hh:1296
#define GEO_NODE_INPUT_ACTIVE_CAMERA
Definition BKE_node.hh:1349
#define GEO_NODE_COLLECTION_INFO
Definition BKE_node.hh:1176
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
Definition string.c:45
#define ELEM(...)
typedef double(DMatrix)[4][4]
@ ID_TE
@ ID_IM
@ ID_MA
@ ID_GR
@ ID_OB
@ IDP_STRING_SUB_UTF8
@ IDP_DOUBLE
@ IDP_FLOAT
@ IDP_STRING
@ IDP_BOOLEAN
@ IDP_INT
@ IDP_ARRAY
@ IDP_ID
@ IDP_FLAG_STATIC_TYPE
@ IDP_FLAG_OVERRIDABLE_LIBRARY
#define MAX_NAME
Definition DNA_defs.h:50
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_TEXTURE
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_MATERIAL
@ SOCK_SHADER
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_CUSTOM
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_OBJECT
@ SOCK_STRING
@ SOCK_RGBA
@ SOCK_MENU
@ GEO_NODE_TRANSFORM_SPACE_RELATIVE
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
@ PROP_COLOR
Definition RNA_types.hh:163
@ PROP_EULER
Definition RNA_types.hh:169
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:237
IndexRange index_range() const
Definition BLI_array.hh:349
int64_t size() const
int64_t alignment() const
void * allocate(const int64_t size, const int64_t alignment)
MapType::KeyIterator keys() const
MapType::ItemIterator items() const
void add(const Key &key, const Value &value)
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
constexpr bool is_empty() const
constexpr const char * c_str() const
int64_t size() const
void append(const T &value)
AttributeValidator lookup_validator(const StringRef attribute_id) const
std::optional< AttributeMetaData > lookup_meta_data(const StringRef attribute_id) const
bool domain_supported(const AttrDomain domain) const
int domain_size(const AttrDomain domain) const
static fn::GField Create(std::string name, const CPPType &type, std::optional< std::string > socket_inspection_name=std::nullopt)
virtual std::optional< AttributeAccessor > attributes() const
virtual std::optional< MutableAttributeAccessor > attributes_for_write()
GAttributeWriter lookup_or_add_for_write(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
int add_with_destination(GField field, GVMutableArray dst)
Definition field.cc:743
virtual void * init_storage(LinearAllocator<> &allocator) const
virtual void destruct_storage(void *storage) const
void execute(Params &params, const Context &context) const
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
local_group_size(16, 16) .push_constant(Type texture
int len
KDTree_3d * tree
draw_view in_light_buf[] float
#define GS(x)
Definition iris.cc:202
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
Definition mallocn.cc:110
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
std::unique_ptr< IDProperty, IDPropertyDeleter > create_bool(StringRefNull prop_name, bool value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_BOOLEAN, set its name and value.
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
bool allow_procedural_attribute_access(StringRef attribute_name)
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
QuaternionBase< T > to_quaternion(const AxisAngleBase< T, AngleT > &axis_angle)
EulerXYZBase< float > EulerXYZ
StringRef input_attribute_name_suffix()
static void store_computed_output_attributes(bke::GeometrySet &geometry, const Span< OutputAttributeToStore > attributes_to_store)
StringRef input_use_attribute_suffix()
static void process_nodes_for_depsgraph(const bNodeTree &tree, Set< ID * > &ids, bool &r_needs_own_transform_relation, bool &r_needs_scene_camera_relation, Set< const bNodeTree * > &checked_groups)
static bool old_id_property_type_matches_socket_convert_to_new_string(const IDProperty &old_property, IDProperty *new_property)
static void store_output_attributes(bke::GeometrySet &geometry, const bNodeTree &tree, const IDProperty *properties, Span< GMutablePointer > output_values)
void update_input_properties_from_node_tree(const bNodeTree &tree, const IDProperty *old_properties, IDProperty &properties, const bool use_name_for_ids)
bool input_has_attribute_toggle(const bNodeTree &node_tree, const int socket_index)
static bool node_needs_own_transform_relation(const bNode &node)
static void id_property_int_update_enum_items(const bNodeSocketValueMenu *value, IDPropertyUIDataInt *ui_data)
void find_node_tree_dependencies(const bNodeTree &tree, Set< ID * > &r_ids, bool &r_needs_own_transform_relation, bool &r_needs_scene_camera_relation)
bool id_property_type_matches_socket(const bNodeTreeInterfaceSocket &socket, const IDProperty &property, const bool use_name_for_ids)
bke::GeometrySet execute_geometry_nodes_on_geometry(const bNodeTree &btree, const IDProperty *properties, const ComputeContext &base_compute_context, GeoNodesCallData &call_data, bke::GeometrySet input_geometry)
std::unique_ptr< IDProperty, bke::idprop::IDPropertyDeleter > id_property_create_from_socket(const bNodeTreeInterfaceSocket &socket, const bool use_name_for_ids)
const GeometryNodesLazyFunctionGraphInfo * ensure_geometry_nodes_lazy_function_graph(const bNodeTree &btree)
bool socket_type_supports_fields(const eNodeSocketDatatype socket_type)
static Vector< OutputAttributeToStore > compute_attributes_to_store(const bke::GeometrySet &geometry, const MultiValueMap< bke::AttrDomain, OutputAttributeInfo > &outputs_by_domain, const bool do_instances)
void update_output_properties_from_node_tree(const bNodeTree &tree, const IDProperty *old_properties, IDProperty &properties)
static void add_used_ids_from_sockets(const ListBase &sockets, Set< ID * > &ids)
static bool old_id_property_type_matches_socket_convert_to_new_float_vec(const IDProperty &old_property, IDProperty *new_property, const int len)
static void init_socket_cpp_value_from_property(const IDProperty &property, const eNodeSocketDatatype socket_value_type, void *r_value)
static MultiValueMap< bke::AttrDomain, OutputAttributeInfo > find_output_attributes_to_store(const bNodeTree &tree, const IDProperty *properties, Span< GMutablePointer > output_values)
bool socket_type_has_attribute_toggle(const eNodeSocketDatatype type)
static void initialize_group_input(const bNodeTree &tree, const IDProperty *properties, const int input_index, void *r_value)
static std::unique_ptr< IDProperty, bke::idprop::IDPropertyDeleter > id_name_or_value_prop(const StringRefNull identifier, ID *id, const std::optional< ID_Type > id_type, const bool use_name_for_ids)
std::optional< StringRef > input_attribute_name_get(const IDProperty &props, const bNodeTreeInterfaceSocket &io_input)
static bool old_id_property_type_matches_socket_convert_to_new(const bNodeTreeInterfaceSocket &socket, const IDProperty &old_property, IDProperty *new_property, const bool use_name_for_ids)
static bool old_id_property_type_matches_socket_convert_to_new_int(const IDProperty &old_property, IDProperty *new_property)
VecBase< int32_t, 4 > int4
VecBase< float, 4 > float4
VecBase< int32_t, 3 > int3
VecBase< double, 3 > double3
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
VecBase< float, 3 > float3
VecBase< double, 4 > double4
bool is_layer_selection_field(const bNodeTreeInterfaceSocket &socket)
#define FLT_MAX
Definition stdcycles.h:14
void * pointer
Definition DNA_ID.h:145
IDPropertyUIData base
Definition DNA_ID.h:109
IDPropertyUIData base
Definition DNA_ID.h:82
IDPropertyUIDataEnumItem * enum_items
Definition DNA_ID.h:94
IDPropertyUIData base
Definition DNA_ID.h:126
char * description
Definition DNA_ID.h:59
short flag
Definition DNA_ID.h:161
int len
Definition DNA_ID.h:174
IDPropertyUIData * ui_data
Definition DNA_ID.h:182
IDPropertyData data
Definition DNA_ID.h:168
char subtype
Definition DNA_ID.h:159
char type
Definition DNA_ID.h:154
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
struct Collection * value
struct Material * value
const RuntimeNodeEnumItemsHandle * enum_items
void * storage
int16_t type
fn::GField validate_field_if_necessary(const fn::GField &field) const
Defines a socket type.
Definition BKE_node.hh:151
const blender::CPPType * geometry_nodes_cpp_type
Definition BKE_node.hh:195
SocketGetGeometryNodesCPPValueFunction get_geometry_nodes_cpp_value
Definition BKE_node.hh:197
const blender::CPPType * base_cpp_type
Definition BKE_node.hh:191
struct blender::nodes::GeometryNodesGroupFunction::@000115334025155014211241101024303251321212251042::@165376366322230201261276177143336154337260306235 attributes_to_propagate
struct blender::nodes::GeometryNodesGroupFunction::@000115334025155014211241101024303251321212251042 inputs
struct blender::nodes::GeometryNodesGroupFunction::@375130375132166273253121104163076122003103003070 outputs
wmTimer * timer
PointerRNA * ptr
Definition wm_files.cc:4126