Blender V4.3
node_geo_foreach_geometry_element.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "BLI_string_utf8.h"
8
9#include "BLO_read_write.hh"
10
11#include "RNA_access.hh"
12#include "RNA_prototypes.hh"
13
17
18#include "UI_interface.hh"
19#include "UI_resources.hh"
20
21#include "BKE_screen.hh"
22
23#include "WM_api.hh"
24
26
27static void draw_item(uiList * /*ui_list*/,
28 const bContext *C,
29 uiLayout *layout,
30 PointerRNA * /*idataptr*/,
31 PointerRNA *itemptr,
32 int /*icon*/,
33 PointerRNA * /*active_dataptr*/,
34 const char * /*active_propname*/,
35 int /*index*/,
36 int /*flt_flag*/)
37{
38 uiLayout *row = uiLayoutRow(layout, true);
39 float4 color;
40 RNA_float_get_array(itemptr, "color", color);
41 uiTemplateNodeSocket(row, const_cast<bContext *>(C), color);
43 uiItemR(row, itemptr, "name", UI_ITEM_NONE, "", ICON_NONE);
44}
45
47static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *current_node_ptr)
48{
49 bNodeTree &ntree = *reinterpret_cast<bNodeTree *>(current_node_ptr->owner_id);
50 bNode *current_node = static_cast<bNode *>(current_node_ptr->data);
51
52 const bke::bNodeTreeZones *zones = ntree.zones();
53 if (!zones) {
54 return;
55 }
56 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(current_node->identifier);
57 if (!zone) {
58 return;
59 }
60 if (!zone->output_node) {
61 return;
62 }
63 const bool is_zone_input_node = current_node->type == GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT;
64 bNode &output_node = const_cast<bNode &>(*zone->output_node);
65 PointerRNA output_node_ptr = RNA_pointer_create(
66 current_node_ptr->owner_id, &RNA_Node, &output_node);
67 auto &storage = *static_cast<NodeGeometryForeachGeometryElementOutput *>(output_node.storage);
68
69 if (is_zone_input_node) {
70 if (uiLayout *panel = uiLayoutPanel(C, layout, "input", false, TIP_("Input Fields"))) {
71 static const uiListType *input_items_list = []() {
72 uiListType *list = MEM_cnew<uiListType>(__func__);
73 STRNCPY(list->idname, "DATA_UL_foreach_geometry_element_input_items");
74 list->draw_item = draw_item;
76 return list;
77 }();
78 uiLayout *row = uiLayoutRow(panel, false);
80 C,
81 input_items_list->idname,
82 "",
83 &output_node_ptr,
84 "input_items",
85 &output_node_ptr,
86 "active_input_index",
87 nullptr,
88 3,
89 5,
91 0,
93 {
94 uiLayout *ops_col = uiLayoutColumn(row, false);
95 {
96 uiLayout *add_remove_col = uiLayoutColumn(ops_col, true);
97 uiItemO(
98 add_remove_col, "", ICON_ADD, "node.foreach_geometry_element_zone_input_item_add");
99 uiItemO(add_remove_col,
100 "",
101 ICON_REMOVE,
102 "node.foreach_geometry_element_zone_input_item_remove");
103 }
104 {
105 uiLayout *up_down_col = uiLayoutColumn(ops_col, true);
106 uiItemEnumO(up_down_col,
107 "node.foreach_geometry_element_zone_input_item_move",
108 "",
109 ICON_TRIA_UP,
110 "direction",
111 0);
112 uiItemEnumO(up_down_col,
113 "node.foreach_geometry_element_zone_input_item_move",
114 "",
115 ICON_TRIA_DOWN,
116 "direction",
117 1);
118 }
119 }
120
121 if (storage.input_items.active_index >= 0 &&
122 storage.input_items.active_index < storage.input_items.items_num)
123 {
125 storage.input_items.items[storage.input_items.active_index];
127 output_node_ptr.owner_id,
129 &active_item);
130 uiLayoutSetPropSep(panel, true);
131 uiLayoutSetPropDecorate(panel, false);
132 uiItemR(panel, &item_ptr, "socket_type", UI_ITEM_NONE, nullptr, ICON_NONE);
133 }
134 }
135 }
136 else {
137 if (uiLayout *panel = uiLayoutPanel(C, layout, "main_items", false, TIP_("Main Geometry"))) {
138 static const uiListType *main_items_list = []() {
139 uiListType *list = MEM_cnew<uiListType>(__func__);
140 STRNCPY(list->idname, "DATA_UL_foreach_geometry_element_main_items");
141 list->draw_item = draw_item;
142 WM_uilisttype_add(list);
143 return list;
144 }();
145 uiLayout *row = uiLayoutRow(panel, false);
146 uiTemplateList(row,
147 C,
148 main_items_list->idname,
149 "",
150 &output_node_ptr,
151 "main_items",
152 &output_node_ptr,
153 "active_main_index",
154 nullptr,
155 3,
156 5,
158 0,
160 {
161 uiLayout *ops_col = uiLayoutColumn(row, false);
162 {
163 uiLayout *add_remove_col = uiLayoutColumn(ops_col, true);
164 uiItemO(
165 add_remove_col, "", ICON_ADD, "node.foreach_geometry_element_zone_main_item_add");
166 uiItemO(add_remove_col,
167 "",
168 ICON_REMOVE,
169 "node.foreach_geometry_element_zone_main_item_remove");
170 }
171 {
172 uiLayout *up_down_col = uiLayoutColumn(ops_col, true);
173 uiItemEnumO(up_down_col,
174 "node.foreach_geometry_element_zone_main_item_move",
175 "",
176 ICON_TRIA_UP,
177 "direction",
178 0);
179 uiItemEnumO(up_down_col,
180 "node.foreach_geometry_element_zone_main_item_move",
181 "",
182 ICON_TRIA_DOWN,
183 "direction",
184 1);
185 }
186 }
187
188 if (storage.main_items.active_index >= 0 &&
189 storage.main_items.active_index < storage.main_items.items_num)
190 {
192 storage.main_items.items[storage.main_items.active_index];
194 output_node_ptr.owner_id,
196 &active_item);
197 uiLayoutSetPropSep(panel, true);
198 uiLayoutSetPropDecorate(panel, false);
199 uiItemR(panel, &item_ptr, "socket_type", UI_ITEM_NONE, nullptr, ICON_NONE);
200 }
201 }
202 if (uiLayout *panel = uiLayoutPanel(
203 C, layout, "generation_items", false, TIP_("Generated Geometry")))
204 {
205 static const uiListType *generation_items_list = []() {
206 uiListType *list = MEM_cnew<uiListType>(__func__);
207 STRNCPY(list->idname, "DATA_UL_foreach_geometry_element_generation_items");
208 list->draw_item = draw_item;
209 WM_uilisttype_add(list);
210 return list;
211 }();
212 uiLayout *row = uiLayoutRow(panel, false);
213 uiTemplateList(row,
214 C,
215 generation_items_list->idname,
216 "",
217 &output_node_ptr,
218 "generation_items",
219 &output_node_ptr,
220 "active_generation_index",
221 nullptr,
222 3,
223 5,
225 0,
227 {
228 uiLayout *ops_col = uiLayoutColumn(row, false);
229 {
230 uiLayout *add_remove_col = uiLayoutColumn(ops_col, true);
231 uiItemO(add_remove_col,
232 "",
233 ICON_ADD,
234 "node.foreach_geometry_element_zone_generation_item_add");
235 uiItemO(add_remove_col,
236 "",
237 ICON_REMOVE,
238 "node.foreach_geometry_element_zone_generation_item_remove");
239 }
240 {
241 uiLayout *up_down_col = uiLayoutColumn(ops_col, true);
242 uiItemEnumO(up_down_col,
243 "node.foreach_geometry_element_zone_generation_item_move",
244 "",
245 ICON_TRIA_UP,
246 "direction",
247 0);
248 uiItemEnumO(up_down_col,
249 "node.foreach_geometry_element_zone_generation_item_move",
250 "",
251 ICON_TRIA_DOWN,
252 "direction",
253 1);
254 }
255 }
256
257 if (storage.generation_items.active_index >= 0 &&
258 storage.generation_items.active_index < storage.generation_items.items_num)
259 {
261 storage.generation_items.items[storage.generation_items.active_index];
263 output_node_ptr.owner_id,
265 &active_item);
266 uiLayoutSetPropSep(panel, true);
267 uiLayoutSetPropDecorate(panel, false);
268 uiItemR(panel, &item_ptr, "socket_type", UI_ITEM_NONE, nullptr, ICON_NONE);
269 if (active_item.socket_type != SOCK_GEOMETRY) {
270 uiItemR(panel, &item_ptr, "domain", UI_ITEM_NONE, nullptr, ICON_NONE);
271 }
272 }
273 }
274 }
275
276 uiItemR(layout, &output_node_ptr, "inspection_index", UI_ITEM_NONE, nullptr, ICON_NONE);
277}
278
279namespace input_node {
280
282
284{
285 b.use_custom_socket_order();
286 b.allow_any_socket_order();
287 const bNode *node = b.node_or_null();
288 const bNodeTree *tree = b.tree_or_null();
289
290 if (!node || !tree) {
291 return;
292 }
293
294 const NodeGeometryForeachGeometryElementInput &storage = node_storage(*node);
295 const bNode *output_node = tree->node_by_id(storage.output_node_id);
296 const auto &output_storage = output_node ?
297 static_cast<const NodeGeometryForeachGeometryElementOutput *>(
298 output_node->storage) :
299 nullptr;
300
301 b.add_output<decl::Int>("Index").description(
302 "Index of the element in the source geometry. Note that the same index can occure more than "
303 "once when iterating over multiple components at once");
304
305 b.add_output<decl::Geometry>("Element")
306 .description(
307 "Single element geometry for the current iteration. Note that it can be quite "
308 "inefficient to splitup large geometries into many small geometries")
309 .propagate_all()
310 .available(output_storage && AttrDomain(output_storage->domain) != AttrDomain::Corner);
311
312 b.add_input<decl::Geometry>("Geometry").description("Geometry whose elements are iterated over");
313
314 b.add_input<decl::Bool>("Selection")
315 .default_value(true)
316 .hide_value()
317 .field_on_all()
318 .description("Selection on the iteration domain");
319
320 if (output_storage) {
321 for (const int i : IndexRange(output_storage->input_items.items_num)) {
322 const NodeForeachGeometryElementInputItem &item = output_storage->input_items.items[i];
323 const eNodeSocketDatatype socket_type = eNodeSocketDatatype(item.socket_type);
324 const StringRef name = item.name ? item.name : "";
325 const std::string identifier =
327 b.add_input(socket_type, name, identifier)
328 .socket_name_ptr(
330 .description("Field that is evaluated on the iteration domain")
331 .field_on_all();
332 b.add_output(socket_type, name, identifier)
333 .align_with_previous()
334 .description("Evaluated field value for the current element");
335 }
336 }
337
338 b.add_input<decl::Extend>("", "__extend__");
339 b.add_output<decl::Extend>("", "__extend__").align_with_previous();
340}
341
342static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
343{
344 bNodeTree &tree = *reinterpret_cast<bNodeTree *>(ptr->owner_id);
345 bNode &node = *static_cast<bNode *>(ptr->data);
346 const NodeGeometryForeachGeometryElementInput &storage = node_storage(node);
347 bNode *output_node = tree.node_by_id(storage.output_node_id);
348
349 PointerRNA output_node_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Node, output_node);
350 uiItemR(layout, &output_node_ptr, "domain", UI_ITEM_NONE, "", ICON_NONE);
351}
352
353static void node_init(bNodeTree * /*tree*/, bNode *node)
354{
356 MEM_cnew<NodeGeometryForeachGeometryElementInput>(__func__);
357 /* Needs to be initialized for the node to work. */
358 data->output_node_id = 0;
359 node->storage = data;
360}
361
362static void node_label(const bNodeTree * /*ntree*/,
363 const bNode * /*node*/,
364 char *label,
365 const int label_maxncpy)
366{
367 BLI_strncpy_utf8(label, IFACE_("For Each Element"), label_maxncpy);
368}
369
370static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
371{
372 bNode *output_node = ntree->node_by_id(node_storage(*node).output_node_id);
373 if (!output_node) {
374 return true;
375 }
377 ForeachGeometryElementInputItemsAccessor>(*ntree, *node, *output_node, *link);
378}
379
380static void node_register()
381{
382 static blender::bke::bNodeType ntype;
383 geo_node_type_base(&ntype,
384 GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT,
385 "For Each Geometry Element Input",
387 ntype.initfunc = node_init;
388 ntype.declare = node_declare;
391 ntype.labelfunc = node_label;
393 ntype.gather_link_search_ops = nullptr;
394 ntype.no_muting = true;
396 "NodeGeometryForeachGeometryElementInput",
400}
402
403} // namespace input_node
404
405namespace output_node {
406
408
410{
411 b.use_custom_socket_order();
412 b.allow_any_socket_order();
413
414 b.add_output<decl::Geometry>("Geometry")
415 .description(
416 "The original input geometry with potentially new attributes that are output by the "
417 "zone");
418
419 aal::RelationsInNode &relations = b.get_anonymous_attribute_relations();
420
421 const bNode *node = b.node_or_null();
422 const bNodeTree *tree = b.tree_or_null();
423 if (node && tree) {
424 const NodeGeometryForeachGeometryElementOutput &storage = node_storage(*node);
425 for (const int i : IndexRange(storage.main_items.items_num)) {
426 const NodeForeachGeometryElementMainItem &item = storage.main_items.items[i];
427 const eNodeSocketDatatype socket_type = eNodeSocketDatatype(item.socket_type);
428 const StringRef name = item.name ? item.name : "";
430 item);
431 b.add_input(socket_type, name, identifier)
432 .socket_name_ptr(
434 .description(
435 "Attribute value that will be stored for the current element on the main geometry");
436 b.add_output(socket_type, name, identifier)
437 .align_with_previous()
438 .field_on({0})
439 .description("Attribute on the geometry above");
440 }
441 b.add_input<decl::Extend>("", "__extend__main");
442 b.add_output<decl::Extend>("", "__extend__main").align_with_previous();
443
444 auto &panel = b.add_panel("Generated");
445
446 int previous_output_geometry_index = -1;
447 int previous_input_geometry_index = -1;
448 for (const int i : IndexRange(storage.generation_items.items_num)) {
450 const eNodeSocketDatatype socket_type = eNodeSocketDatatype(item.socket_type);
451 if (socket_type == SOCK_GEOMETRY && i > 0) {
452 panel.add_separator();
453 }
454 const StringRef name = item.name ? item.name : "";
455 std::string identifier =
457 auto &input_decl = panel.add_input(socket_type, name, identifier)
458 .socket_name_ptr(
459 &tree->id,
461 &item,
462 "name");
463 auto &output_decl = panel.add_output(socket_type, name, identifier).align_with_previous();
464 if (socket_type == SOCK_GEOMETRY) {
465 previous_input_geometry_index = input_decl.index();
466 previous_output_geometry_index = output_decl.index();
467 aal::PropagateRelation relation;
468 relation.from_geometry_input = input_decl.index();
469 relation.to_geometry_output = output_decl.index();
470 relations.propagate_relations.append(relation);
471
472 input_decl.description(
473 "Geometry generated in the current iteration. Will be joined with geometries from all "
474 "other iterations");
475 output_decl.description("Result of joining generated geometries from each iteration");
476 }
477 else {
478 if (previous_output_geometry_index > 0) {
479 input_decl.description("Field that will be stored as attribute on the geometry above");
480 input_decl.field_on({previous_input_geometry_index});
481 output_decl.field_on({previous_output_geometry_index});
482 }
483 output_decl.description("Attribute on the geometry above");
484 }
485 }
486 panel.add_input<decl::Extend>("", "__extend__generation");
487 panel.add_output<decl::Extend>("", "__extend__generation").align_with_previous();
488 }
489}
490
491static void node_init(bNodeTree * /*tree*/, bNode *node)
492{
494 MEM_cnew<NodeGeometryForeachGeometryElementOutput>(__func__);
495
496 data->generation_items.items = MEM_cnew_array<NodeForeachGeometryElementGenerationItem>(
497 1, __func__);
498 NodeForeachGeometryElementGenerationItem &item = data->generation_items.items[0];
499 item.name = BLI_strdup(DATA_("Geometry"));
501 item.identifier = data->generation_items.next_identifier++;
502 data->generation_items.items_num = 1;
503
504 node->storage = data;
505}
506
514
515static void node_copy_storage(bNodeTree * /*dst_tree*/, bNode *dst_node, const bNode *src_node)
516{
517 const NodeGeometryForeachGeometryElementOutput &src_storage = node_storage(*src_node);
518 auto *dst_storage = MEM_cnew<NodeGeometryForeachGeometryElementOutput>(__func__, src_storage);
519 dst_node->storage = dst_storage;
520
524}
525
526static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
527{
529 *ntree, *node, *node, *link, "__extend__main"))
530 {
531 return false;
532 }
535}
536
538{
540 ot, "Remove For Each Input Item", __func__, "Remove active for-each input item");
541}
542
544{
546 ot, "Add For Each Input Item", __func__, "Add for-each input item");
547}
548
550{
552 ot, "Move For Each Input Item", __func__, "Move active for-each input item");
553}
554
556{
558 ot, "Remove For Each Generation Item", __func__, "Remove active for-each generation item");
559}
560
562{
564 ot, "Add For Each Generation Item", __func__, "Add for-each generation item");
565}
566
568{
570 ot, "Move For Each Generation Item", __func__, "Move active for-each generation item");
571}
572
574{
576 ot, "Remove For Each Main Item", __func__, "Remove active for-each main item");
577}
578
580{
582 ot, "Add For Each Main Item", __func__, "Add for-each main item");
583}
584
586{
588 ot, "Move For Each Main Item", __func__, "Move active for-each main item");
589}
590
605
607{
608 const NodeGeometryForeachGeometryElementOutput &storage = node_storage(params.node);
609 if (storage.generation_items.items_num > 0) {
612 row.text = RPT_("Missing Geometry");
613 row.tooltip = TIP_("Each output field has to correspond to a geometry that is above it");
614 row.icon = ICON_ERROR;
615 params.rows.append(std::move(row));
616 }
617 }
618}
619
620static void node_register()
621{
622 static blender::bke::bNodeType ntype;
623 geo_node_type_base(&ntype,
624 GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT,
625 "For Each Geometry Element Output",
627 ntype.initfunc = node_init;
628 ntype.declare = node_declare;
634 ntype.no_muting = true;
636 &ntype, "NodeGeometryForeachGeometryElementOutput", node_free_storage, node_copy_storage);
638}
640
641} // namespace output_node
642
643} // namespace blender::nodes::node_geo_foreach_geometry_element_cc
644
645namespace blender::nodes {
646
648 &RNA_ForeachGeometryElementInputItem;
650
652{
653 const auto &storage = *static_cast<const NodeGeometryForeachGeometryElementOutput *>(
654 node.storage);
657 storage.input_items.items_num,
658 storage.input_items.items);
659 for (const NodeForeachGeometryElementInputItem &item :
660 Span(storage.input_items.items, storage.input_items.items_num))
661 {
662 BLO_write_string(writer, item.name);
663 }
664}
665
667 bNode &node)
668{
669 auto &storage = *static_cast<NodeGeometryForeachGeometryElementOutput *>(node.storage);
672 storage.input_items.items_num,
673 &storage.input_items.items);
674 for (const NodeForeachGeometryElementInputItem &item :
675 Span(storage.input_items.items, storage.input_items.items_num))
676 {
677 BLO_read_string(reader, &item.name);
678 }
679}
680
682 &RNA_ForeachGeometryElementMainItem;
684
686{
687 const auto &storage = *static_cast<const NodeGeometryForeachGeometryElementOutput *>(
688 node.storage);
691 storage.main_items.items_num,
692 storage.main_items.items);
693 for (const NodeForeachGeometryElementMainItem &item :
694 Span(storage.main_items.items, storage.main_items.items_num))
695 {
696 BLO_write_string(writer, item.name);
697 }
698}
699
701{
702 auto &storage = *static_cast<NodeGeometryForeachGeometryElementOutput *>(node.storage);
705 storage.main_items.items_num,
706 &storage.main_items.items);
707 for (const NodeForeachGeometryElementMainItem &item :
708 Span(storage.main_items.items, storage.main_items.items_num))
709 {
710 BLO_read_string(reader, &item.name);
711 }
712}
713
715 &RNA_ForeachGeometryElementGenerationItem;
718
720 const bNode &node)
721{
722 const auto &storage = *static_cast<const NodeGeometryForeachGeometryElementOutput *>(
723 node.storage);
726 storage.generation_items.items_num,
727 storage.generation_items.items);
729 Span(storage.generation_items.items, storage.generation_items.items_num))
730 {
731 BLO_write_string(writer, item.name);
732 }
733}
734
736 bNode &node)
737{
738 auto &storage = *static_cast<NodeGeometryForeachGeometryElementOutput *>(node.storage);
741 storage.generation_items.items_num,
742 &storage.generation_items.items);
744 Span(storage.generation_items.items, storage.generation_items.items_num))
745 {
746 BLO_read_string(reader, &item.name);
747 }
748}
749
750} // namespace blender::nodes
#define NODE_CLASS_INTERFACE
Definition BKE_node.hh:416
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT
Definition BKE_node.hh:1378
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1799
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT
Definition BKE_node.hh:1379
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
Definition readfile.cc:4992
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define RPT_(msgid)
#define TIP_(msgid)
#define IFACE_(msgid)
#define DATA_(msgid)
eNodeSocketDatatype
@ SOCK_GEOMETRY
@ UILST_LAYOUT_DEFAULT
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ UI_EMBOSS_NONE
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemEnumO(uiLayout *layout, const char *opname, const char *name, int icon, const char *propname, int value)
void uiTemplateList(uiLayout *layout, const bContext *C, const char *listtype_name, const char *list_id, PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, const char *active_propname, const char *item_dyntip_propname, int rows, int maxrows, int layout_type, int columns, enum uiTemplateListFlags flags)
#define UI_ITEM_NONE
PanelLayout uiLayoutPanel(const bContext *C, uiLayout *layout, const char *idname, bool default_closed)
void uiTemplateNodeSocket(uiLayout *layout, bContext *C, const float color[4])
void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss)
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
@ UI_TEMPLATE_LIST_FLAG_NONE
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
local_group_size(16, 16) .push_constant(Type b
OperationNode * node
const char * label
KDTree_3d * tree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
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
static void node_label(const bNodeTree *, const bNode *, char *label, const int label_maxncpy)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
static void node_copy_storage(bNodeTree *, bNode *dst_node, const bNode *src_node)
static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *current_node_ptr)
static void draw_item(uiList *, const bContext *C, uiLayout *layout, PointerRNA *, PointerRNA *itemptr, int, PointerRNA *, const char *, int, int)
void move_active_item(wmOperatorType *ot, const char *name, const char *idname, const char *description)
void remove_active_item(wmOperatorType *ot, const char *name, const char *idname, const char *description)
void add_item(wmOperatorType *ot, const char *name, const char *idname, const char *description)
void copy_array(const bNode &src_node, bNode &dst_node)
bool try_add_item_via_any_extend_socket(bNodeTree &ntree, bNode &extend_node, bNode &storage_node, bNodeLink &link, const std::optional< StringRef > socket_identifier=std::nullopt)
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
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
NodeForeachGeometryElementGenerationItem * items
NodeForeachGeometryElementMainItem * items
NodeForeachGeometryElementMainItems main_items
NodeForeachGeometryElementGenerationItems generation_items
ID * owner_id
Definition RNA_types.hh:40
void * data
Definition RNA_types.hh:42
void * storage
int32_t identifier
int16_t type
Defines a node type.
Definition BKE_node.hh:218
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
void(* labelfunc)(const bNodeTree *ntree, const bNode *node, char *label, int label_maxncpy)
Definition BKE_node.hh:249
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:240
NodeExtraInfoFunction get_extra_info
Definition BKE_node.hh:366
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:363
bool(* insert_link)(bNodeTree *ntree, bNode *node, bNodeLink *link)
Definition BKE_node.hh:309
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* register_operators)()
Definition BKE_node.hh:392
static void blend_read_data(BlendDataReader *reader, bNode &node)
static void blend_write(BlendWriter *writer, const bNode &node)
static void blend_read_data(BlendDataReader *reader, bNode &node)
static void blend_write(BlendWriter *writer, const bNode &node)
char idname[BKE_ST_MAXNAME]
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
bool WM_uilisttype_add(uiListType *ult)