12#include "RNA_prototypes.hh"
37 bNode *current_node =
static_cast<bNode *
>(current_node_ptr->
data);
50 const bool is_zone_input_node = current_node->
type_legacy ==
57 if (is_zone_input_node) {
63 panel->use_property_split_set(
true);
64 panel->use_property_decorate_set(
false);
65 panel->prop(item_ptr,
"socket_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
75 panel->use_property_split_set(
true);
76 panel->use_property_decorate_set(
false);
77 panel->prop(item_ptr,
"socket_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
81 C,
"generation_items",
false,
IFACE_(
"Generated Geometry")))
88 storage.generation_items.items[storage.generation_items.active_index];
89 panel->use_property_split_set(
true);
90 panel->use_property_decorate_set(
false);
91 panel->prop(item_ptr,
"socket_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
93 panel->prop(item_ptr,
"domain",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
99 layout->
prop(&output_node_ptr,
"inspection_index",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
108 b.use_custom_socket_order();
109 b.allow_any_socket_order();
110 const bNode *node =
b.node_or_null();
113 b.add_default_layout();
115 if (!node || !
tree) {
127 "Index of the element in the source geometry. Note that the same index can occur more than "
128 "once when iterating over multiple components at once");
132 "Single-element geometry for the current iteration. Note that it can be quite "
133 "inefficient to split up large geometries into many small geometries")
135 .available(output_storage &&
AttrDomain(output_storage->domain) != AttrDomain::Corner);
137 b.add_input<
decl::Geometry>(
"Geometry").description(
"Geometry whose elements are iterated over");
143 .description(
"Selection on the iteration domain");
145 if (output_storage) {
146 for (
const int i :
IndexRange(output_storage->input_items.items_num)) {
150 const std::string identifier =
152 b.add_input(socket_type,
name, identifier)
155 .description(
"Field that is evaluated on the iteration domain")
157 b.add_output(socket_type,
name, identifier)
158 .align_with_previous()
159 .description(
"Evaluated field value for the current element");
163 b.add_input<
decl::Extend>(
"",
"__extend__").structure_type(StructureType::Dynamic);
165 .structure_type(StructureType::Dynamic)
166 .align_with_previous();
185 data->output_node_id = 0;
192 const int label_maxncpy)
214 ntype.
ui_name =
"For Each Geometry Element Input";
226 "NodeGeometryForeachGeometryElementInput",
241 b.use_custom_socket_order();
242 b.allow_any_socket_order();
246 "The original input geometry with potentially new attributes that are output by the "
249 const bNode *node =
b.node_or_null();
259 b.add_input(socket_type,
name, identifier)
263 "Attribute value that will be stored for the current element on the main geometry");
264 b.add_output(socket_type,
name, identifier)
265 .align_with_previous()
267 .description(
"Attribute on the geometry above");
270 b.add_output<
decl::Extend>(
"",
"__extend__main").align_with_previous();
272 auto &panel =
b.add_panel(
"Generated");
274 int previous_output_geometry_index = -1;
275 int previous_input_geometry_index = -1;
280 panel.add_separator();
283 std::string identifier =
285 auto &input_decl = panel.add_input(socket_type,
name, identifier)
291 auto &output_decl = panel.add_output(socket_type,
name, identifier).align_with_previous();
293 previous_input_geometry_index = input_decl.index();
294 previous_output_geometry_index = output_decl.index();
296 input_decl.description(
297 "Geometry generated in the current iteration. Will be joined with geometries from all "
299 output_decl.description(
"Result of joining generated geometries from each iteration");
302 if (previous_output_geometry_index > 0) {
303 input_decl.description(
"Field that will be stored as attribute on the geometry above");
304 input_decl.field_on({previous_input_geometry_index});
305 output_decl.field_on({previous_output_geometry_index});
307 output_decl.description(
"Attribute on the geometry above");
310 panel.add_input<
decl::Extend>(
"",
"__extend__generation");
311 panel.add_output<
decl::Extend>(
"",
"__extend__generation").align_with_previous();
326 data->generation_items.items_num = 1;
344 dst_node->
storage = dst_storage;
376 row.
text =
RPT_(
"Missing Geometry");
377 row.
tooltip =
TIP_(
"Each output field has to correspond to a geometry that is above it");
378 row.
icon = ICON_ERROR;
379 params.rows.append(std::move(row));
411 params.add_item_full_name(
419 params.add_item_full_name(
423 params.node_tree.ensure_topology_cache();
451 "GeometryNodeForeachGeometryElementOutput",
453 ntype.
ui_name =
"For Each Geometry Element Output";
480 &RNA_ForeachGeometryElementInputItem;
495 &RNA_ForeachGeometryElementMainItem;
510 &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 BLT_I18NCONTEXT_ID_NODETREE
#define CTX_IFACE_(context, msgid)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
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(bke::NodeInsertLinkParams ¶ms)
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, typename Accessor::ItemT **r_new_item=nullptr)
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)
bool(* insert_link)(NodeInsertLinkParams ¶ms)
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
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)