12#include "RNA_prototypes.hh"
35 bNode *current_node =
static_cast<bNode *
>(current_node_ptr->
data);
48 const bool is_zone_input_node = current_node->
type_legacy ==
55 if (is_zone_input_node) {
63 panel->prop(item_ptr,
"socket_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
75 panel->prop(item_ptr,
"socket_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
79 C,
"generation_items",
false,
IFACE_(
"Generated Geometry")))
86 storage.generation_items.items[storage.generation_items.active_index];
89 panel->prop(item_ptr,
"socket_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
91 panel->prop(item_ptr,
"domain",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
97 layout->
prop(&output_node_ptr,
"inspection_index",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
106 b.use_custom_socket_order();
107 b.allow_any_socket_order();
108 const bNode *node =
b.node_or_null();
111 b.add_default_layout();
113 if (!node || !
tree) {
125 "Index of the element in the source geometry. Note that the same index can occur more than "
126 "once when iterating over multiple components at once");
130 "Single-element geometry for the current iteration. Note that it can be quite "
131 "inefficient to split up large geometries into many small geometries")
133 .available(output_storage &&
AttrDomain(output_storage->domain) != AttrDomain::Corner);
135 b.add_input<
decl::Geometry>(
"Geometry").description(
"Geometry whose elements are iterated over");
141 .description(
"Selection on the iteration domain");
143 if (output_storage) {
144 for (
const int i :
IndexRange(output_storage->input_items.items_num)) {
148 const std::string identifier =
150 b.add_input(socket_type, name, identifier)
153 .description(
"Field that is evaluated on the iteration domain")
155 b.add_output(socket_type, name, identifier)
156 .align_with_previous()
157 .description(
"Evaluated field value for the current element");
161 b.add_input<
decl::Extend>(
"",
"__extend__").structure_type(StructureType::Dynamic);
163 .structure_type(StructureType::Dynamic)
164 .align_with_previous();
183 data->output_node_id = 0;
190 const int label_maxncpy)
210 ntype.
ui_name =
"For Each Geometry Element Input";
222 "NodeGeometryForeachGeometryElementInput",
237 b.use_custom_socket_order();
238 b.allow_any_socket_order();
242 "The original input geometry with potentially new attributes that are output by the "
245 const bNode *node =
b.node_or_null();
255 b.add_input(socket_type, name, identifier)
259 "Attribute value that will be stored for the current element on the main geometry");
260 b.add_output(socket_type, name, identifier)
261 .align_with_previous()
263 .description(
"Attribute on the geometry above");
266 b.add_output<
decl::Extend>(
"",
"__extend__main").align_with_previous();
268 auto &panel =
b.add_panel(
"Generated");
270 int previous_output_geometry_index = -1;
271 int previous_input_geometry_index = -1;
276 panel.add_separator();
279 std::string identifier =
281 auto &input_decl = panel.add_input(socket_type, name, identifier)
287 auto &output_decl = panel.add_output(socket_type, name, identifier).align_with_previous();
289 previous_input_geometry_index = input_decl.index();
290 previous_output_geometry_index = output_decl.index();
292 input_decl.description(
293 "Geometry generated in the current iteration. Will be joined with geometries from all "
295 output_decl.description(
"Result of joining generated geometries from each iteration");
298 if (previous_output_geometry_index > 0) {
299 input_decl.description(
"Field that will be stored as attribute on the geometry above");
300 input_decl.field_on({previous_input_geometry_index});
301 output_decl.field_on({previous_output_geometry_index});
303 output_decl.description(
"Attribute on the geometry above");
306 panel.add_input<
decl::Extend>(
"",
"__extend__generation");
307 panel.add_output<
decl::Extend>(
"",
"__extend__generation").align_with_previous();
322 data->generation_items.items_num = 1;
340 dst_node->
storage = dst_storage;
350 *ntree, *node, *node, *link,
"__extend__main"))
371 row.
text =
RPT_(
"Missing Geometry");
372 row.
tooltip =
TIP_(
"Each output field has to correspond to a geometry that is above it");
373 row.
icon = ICON_ERROR;
374 params.rows.append(std::move(row));
406 params.add_item_full_name(
416 params.node_tree.ensure_topology_cache();
444 "GeometryNodeForeachGeometryElementOutput",
446 ntype.
ui_name =
"For Each Geometry Element Output";
473 &RNA_ForeachGeometryElementInputItem;
488 &RNA_ForeachGeometryElementMainItem;
503 &RNA_ForeachGeometryElementGenerationItem;
#define NODE_CLASS_INTERFACE
#define NODE_STORAGE_FUNCS(StorageT)
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
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 NOD_REGISTER_NODE(REGISTER_FUNC)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
BMesh const char void * data
std::optional< int > output_node_id
const bNode * output_node() const
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
void node_register_type(bNodeType &ntype)
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
static void node_extra_info(NodeExtraInfoParams ¶ms)
static void node_copy_storage(bNodeTree *, bNode *dst_node, const bNode *src_node)
static void node_register()
static void node_declare(NodeDeclarationBuilder &b)
static void node_blend_write(const bNodeTree &, const bNode &node, BlendWriter &writer)
static void node_free_storage(bNode *node)
static std::pair< bNode *, bNode * > add_foreach_zone(LinkSearchOpParams ¶ms)
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
static void node_blend_read(bNodeTree &, bNode &node, BlendDataReader &reader)
static void node_operators()
static void node_init(bNodeTree *, bNode *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)
void make_common_operators()
static void draw_items_list_with_operators(const bContext *C, uiLayout *layout, const bNodeTree &tree, const bNode &node)
static void draw_active_item_props(const bNodeTree &tree, const bNode &node, const FunctionRef< void(PointerRNA *item_ptr)> draw_item)
void blend_write(BlendWriter *writer, const bNode &node)
void destruct_array(bNode &node)
void blend_read_data(BlendDataReader *reader, 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, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
#define UI_MENU_ARROW_SEP
NodeForeachGeometryElementGenerationItem * items
NodeForeachGeometryElementMainItem * items
NodeForeachGeometryElementMainItems main_items
NodeForeachGeometryElementGenerationItems generation_items
NodeBlendWriteFunction blend_write_storage_content
NodeBlendDataReadFunction blend_data_read_storage_content
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
const char * enum_name_legacy
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
NodeForeachGeometryElementGenerationItem ItemT
static void blend_write_item(BlendWriter *writer, const ItemT &item)
static void blend_read_data_item(BlendDataReader *reader, ItemT &item)
static std::string socket_identifier_for_item(const ItemT &item)
static StructRNA * item_srna
static std::string socket_identifier_for_item(const ItemT &item)
static void blend_write_item(BlendWriter *writer, const ItemT &item)
NodeForeachGeometryElementMainItem ItemT
static void blend_read_data_item(BlendDataReader *reader, ItemT &item)
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)