12#include "RNA_prototypes.hh"
50 bNode *current_node =
static_cast<bNode *
>(current_node_ptr->
data);
60 if (!zone->output_node) {
64 bNode &output_node =
const_cast<bNode &
>(*zone->output_node);
66 current_node_ptr->
owner_id, &RNA_Node, &output_node);
69 if (is_zone_input_node) {
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");
98 add_remove_col,
"", ICON_ADD,
"node.foreach_geometry_element_zone_input_item_add");
102 "node.foreach_geometry_element_zone_input_item_remove");
107 "node.foreach_geometry_element_zone_input_item_move",
113 "node.foreach_geometry_element_zone_input_item_move",
121 if (storage.input_items.active_index >= 0 &&
122 storage.input_items.active_index < storage.input_items.items_num)
125 storage.input_items.items[storage.input_items.active_index];
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");
165 add_remove_col,
"", ICON_ADD,
"node.foreach_geometry_element_zone_main_item_add");
169 "node.foreach_geometry_element_zone_main_item_remove");
174 "node.foreach_geometry_element_zone_main_item_move",
180 "node.foreach_geometry_element_zone_main_item_move",
188 if (storage.main_items.active_index >= 0 &&
189 storage.main_items.active_index < storage.main_items.items_num)
192 storage.main_items.items[storage.main_items.active_index];
203 C, layout,
"generation_items",
false,
TIP_(
"Generated Geometry")))
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");
215 generation_items_list->
idname,
220 "active_generation_index",
234 "node.foreach_geometry_element_zone_generation_item_add");
238 "node.foreach_geometry_element_zone_generation_item_remove");
243 "node.foreach_geometry_element_zone_generation_item_move",
249 "node.foreach_geometry_element_zone_generation_item_move",
257 if (storage.generation_items.active_index >= 0 &&
258 storage.generation_items.active_index < storage.generation_items.items_num)
261 storage.generation_items.items[storage.generation_items.active_index];
279namespace input_node {
285 b.use_custom_socket_order();
286 b.allow_any_socket_order();
287 const bNode *node =
b.node_or_null();
290 if (!node || !
tree) {
296 const auto &output_storage = output_node ?
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");
307 "Single element geometry for the current iteration. Note that it can be quite "
308 "inefficient to splitup large geometries into many small geometries")
310 .available(output_storage && AttrDomain(output_storage->domain) != AttrDomain::Corner);
312 b.add_input<
decl::Geometry>(
"Geometry").description(
"Geometry whose elements are iterated over");
318 .description(
"Selection on the iteration domain");
320 if (output_storage) {
321 for (
const int i :
IndexRange(output_storage->input_items.items_num)) {
325 const std::string identifier =
327 b.add_input(socket_type, name, identifier)
330 .description(
"Field that is evaluated on the iteration domain")
332 b.add_output(socket_type, name, identifier)
333 .align_with_previous()
334 .description(
"Evaluated field value for the current element");
339 b.add_output<
decl::Extend>(
"",
"__extend__").align_with_previous();
356 MEM_cnew<NodeGeometryForeachGeometryElementInput>(__func__);
358 data->output_node_id = 0;
359 node->storage =
data;
365 const int label_maxncpy)
372 bNode *output_node = ntree->node_by_id(node_storage(*node).output_node_id);
384 GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT,
385 "For Each Geometry Element Input",
396 "NodeGeometryForeachGeometryElementInput",
405namespace output_node {
411 b.use_custom_socket_order();
412 b.allow_any_socket_order();
416 "The original input geometry with potentially new attributes that are output by the "
421 const bNode *node =
b.node_or_null();
431 b.add_input(socket_type, name, identifier)
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()
439 .description(
"Attribute on the geometry above");
442 b.add_output<
decl::Extend>(
"",
"__extend__main").align_with_previous();
444 auto &panel =
b.add_panel(
"Generated");
446 int previous_output_geometry_index = -1;
447 int previous_input_geometry_index = -1;
452 panel.add_separator();
455 std::string identifier =
457 auto &input_decl = panel.add_input(socket_type, name, identifier)
463 auto &output_decl = panel.add_output(socket_type, name, identifier).align_with_previous();
465 previous_input_geometry_index = input_decl.index();
466 previous_output_geometry_index = output_decl.index();
472 input_decl.description(
473 "Geometry generated in the current iteration. Will be joined with geometries from all "
475 output_decl.description(
"Result of joining generated geometries from each iteration");
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});
483 output_decl.description(
"Attribute on the geometry above");
486 panel.add_input<
decl::Extend>(
"",
"__extend__generation");
487 panel.add_output<
decl::Extend>(
"",
"__extend__generation").align_with_previous();
494 MEM_cnew<NodeGeometryForeachGeometryElementOutput>(__func__);
496 data->generation_items.items = MEM_cnew_array<NodeForeachGeometryElementGenerationItem>(
501 item.
identifier = data->generation_items.next_identifier++;
502 data->generation_items.items_num = 1;
504 node->storage =
data;
518 auto *dst_storage = MEM_cnew<NodeGeometryForeachGeometryElementOutput>(__func__, src_storage);
519 dst_node->
storage = dst_storage;
529 *ntree, *node, *node, *link,
"__extend__main"))
540 ot,
"Remove For Each Input Item", __func__,
"Remove active for-each input item");
546 ot,
"Add For Each Input Item", __func__,
"Add for-each input item");
552 ot,
"Move For Each Input Item", __func__,
"Move active for-each input item");
558 ot,
"Remove For Each Generation Item", __func__,
"Remove active for-each generation item");
564 ot,
"Add For Each Generation Item", __func__,
"Add for-each generation item");
570 ot,
"Move For Each Generation Item", __func__,
"Move active for-each generation item");
576 ot,
"Remove For Each Main Item", __func__,
"Remove active for-each main item");
582 ot,
"Add For Each Main Item", __func__,
"Add for-each main item");
588 ot,
"Move For Each Main Item", __func__,
"Move active for-each main item");
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));
624 GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT,
625 "For Each Geometry Element Output",
648 &RNA_ForeachGeometryElementInputItem;
657 storage.input_items.items_num,
658 storage.input_items.items);
660 Span(storage.input_items.items, storage.input_items.items_num))
672 storage.input_items.items_num,
673 &storage.input_items.items);
675 Span(storage.input_items.items, storage.input_items.items_num))
682 &RNA_ForeachGeometryElementMainItem;
691 storage.main_items.items_num,
692 storage.main_items.items);
694 Span(storage.main_items.items, storage.main_items.items_num))
705 storage.main_items.items_num,
706 &storage.main_items.items);
708 Span(storage.main_items.items, storage.main_items.items_num))
715 &RNA_ForeachGeometryElementGenerationItem;
726 storage.generation_items.items_num,
727 storage.generation_items.items);
729 Span(storage.generation_items.items, storage.generation_items.items_num))
741 storage.generation_items.items_num,
742 &storage.generation_items.items);
744 Span(storage.generation_items.items, storage.generation_items.items_num))
#define NODE_CLASS_INTERFACE
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT
#define NODE_STORAGE_FUNCS(StorageT)
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
#define STRNCPY(dst, src)
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)
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 NOD_REGISTER_NODE(REGISTER_FUNC)
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)
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
void MEM_freeN(void *vmemh)
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))
void node_register_type(bNodeType *ntype)
static void node_extra_info(NodeExtraInfoParams ¶ms)
static void NODE_OT_foreach_geometry_element_zone_main_item_remove(wmOperatorType *ot)
static void node_copy_storage(bNodeTree *, bNode *dst_node, const bNode *src_node)
static void NODE_OT_foreach_geometry_element_zone_main_item_move(wmOperatorType *ot)
static void NODE_OT_foreach_geometry_element_zone_input_item_add(wmOperatorType *ot)
static void NODE_OT_foreach_geometry_element_zone_main_item_add(wmOperatorType *ot)
static void node_register()
static void NODE_OT_foreach_geometry_element_zone_generation_item_add(wmOperatorType *ot)
static void node_declare(NodeDeclarationBuilder &b)
static void node_free_storage(bNode *node)
static void NODE_OT_foreach_geometry_element_zone_generation_item_remove(wmOperatorType *ot)
static void NODE_OT_foreach_geometry_element_zone_input_item_remove(wmOperatorType *ot)
static void NODE_OT_foreach_geometry_element_zone_generation_item_move(wmOperatorType *ot)
static void node_operators()
static void node_init(bNodeTree *, bNode *node)
static void NODE_OT_foreach_geometry_element_zone_input_item_move(wmOperatorType *ot)
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 destruct_array(bNode &node)
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)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
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
void(* initfunc)(bNodeTree *ntree, bNode *node)
void(* labelfunc)(const bNodeTree *ntree, const bNode *node, char *label, int label_maxncpy)
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeExtraInfoFunction get_extra_info
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
bool(* insert_link)(bNodeTree *ntree, bNode *node, bNodeLink *link)
NodeDeclareFunction declare
void(* register_operators)()
static StructRNA * item_srna
static void blend_write(BlendWriter *writer, const bNode &node)
static std::string socket_identifier_for_item(const ItemT &item)
static void blend_read_data(BlendDataReader *reader, bNode &node)
static StructRNA * item_srna
static void blend_read_data(BlendDataReader *reader, bNode &node)
static std::string socket_identifier_for_item(const ItemT &item)
static void blend_write(BlendWriter *writer, const bNode &node)
Vector< PropagateRelation > propagate_relations
char idname[BKE_ST_MAXNAME]
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
bool WM_uilisttype_add(uiListType *ult)