Blender V4.5
node_geo_repeat.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
5#include "BLI_string.h"
6#include "BLI_string_utf8.h"
7
8#include "NOD_geo_repeat.hh"
9#include "NOD_socket.hh"
14
15#include "BLO_read_write.hh"
16
17#include "RNA_access.hh"
18#include "RNA_prototypes.hh"
19
20#include "BKE_screen.hh"
21
22#include "WM_api.hh"
23
24#include "UI_interface.hh"
25
26#include "node_geometry_util.hh"
27
29
31static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *current_node_ptr)
32{
33 bNodeTree &ntree = *reinterpret_cast<bNodeTree *>(current_node_ptr->owner_id);
34 bNode *current_node = static_cast<bNode *>(current_node_ptr->data);
35
36 const bke::bNodeTreeZones *zones = ntree.zones();
37 if (!zones) {
38 return;
39 }
40 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(current_node->identifier);
41 if (!zone) {
42 return;
43 }
44 if (!zone->output_node_id) {
45 return;
46 }
47 bNode &output_node = const_cast<bNode &>(*zone->output_node());
49 current_node_ptr->owner_id, &RNA_Node, &output_node);
50
51 if (uiLayout *panel = layout->panel(C, "repeat_items", false, IFACE_("Repeat Items"))) {
53 C, panel, ntree, output_node);
55 ntree, output_node, [&](PointerRNA *item_ptr) {
56 uiLayoutSetPropSep(panel, true);
57 uiLayoutSetPropDecorate(panel, false);
58 panel->prop(item_ptr, "socket_type", UI_ITEM_NONE, std::nullopt, ICON_NONE);
59 });
60 }
61
62 layout->prop(&output_node_ptr, "inspection_index", UI_ITEM_NONE, std::nullopt, ICON_NONE);
63}
64
66
68
70{
71 b.use_custom_socket_order();
72 b.allow_any_socket_order();
73 b.add_output<decl::Int>("Iteration")
74 .description("Index of the current iteration. Starts counting at zero");
75 b.add_input<decl::Int>("Iterations").min(0).default_value(1);
76
77 const bNode *node = b.node_or_null();
78 const bNodeTree *tree = b.tree_or_null();
79 if (node && tree) {
80 const NodeGeometryRepeatInput &storage = node_storage(*node);
81 if (const bNode *output_node = tree->node_by_id(storage.output_node_id)) {
82 const auto &output_storage = *static_cast<const NodeGeometryRepeatOutput *>(
83 output_node->storage);
84 for (const int i : IndexRange(output_storage.items_num)) {
85 const NodeRepeatItem &item = output_storage.items[i];
86 const eNodeSocketDatatype socket_type = eNodeSocketDatatype(item.socket_type);
87 const StringRef name = item.name ? item.name : "";
88 const std::string identifier = RepeatItemsAccessor::socket_identifier_for_item(item);
89 auto &input_decl = b.add_input(socket_type, name, identifier)
90 .socket_name_ptr(
91 &tree->id, RepeatItemsAccessor::item_srna, &item, "name");
92 auto &output_decl = b.add_output(socket_type, name, identifier).align_with_previous();
93 if (socket_type_supports_fields(socket_type)) {
94 input_decl.supports_field();
95 output_decl.dependent_field({input_decl.index()});
96 }
97 }
98 }
99 }
100 b.add_input<decl::Extend>("", "__extend__").structure_type(StructureType::Dynamic);
101 b.add_output<decl::Extend>("", "__extend__")
102 .structure_type(StructureType::Dynamic)
103 .align_with_previous();
104}
105
106static void node_init(bNodeTree * /*tree*/, bNode *node)
107{
109 /* Needs to be initialized for the node to work. */
110 data->output_node_id = 0;
111 node->storage = data;
112}
113
114static void node_label(const bNodeTree * /*ntree*/,
115 const bNode * /*node*/,
116 char *label,
117 const int label_maxncpy)
118{
119 BLI_strncpy_utf8(label, IFACE_("Repeat"), label_maxncpy);
120}
121
122static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
123{
124 bNode *output_node = ntree->node_by_id(node_storage(*node).output_node_id);
125 if (!output_node) {
126 return true;
127 }
129 *ntree, *node, *output_node, *link);
130}
131
132static void node_register()
133{
134 static blender::bke::bNodeType ntype;
135 geo_node_type_base(&ntype, "GeometryNodeRepeatInput", GEO_NODE_REPEAT_INPUT);
136 ntype.ui_name = "Repeat Input";
137 ntype.enum_name_legacy = "REPEAT_INPUT";
139 ntype.initfunc = node_init;
140 ntype.declare = node_declare;
141 ntype.labelfunc = node_label;
142 ntype.gather_link_search_ops = nullptr;
144 ntype.no_muting = true;
147 ntype, "NodeGeometryRepeatInput", node_free_standard_storage, node_copy_standard_storage);
149}
151
152} // namespace repeat_input_node
153
155
157
159{
160 b.use_custom_socket_order();
161 b.allow_any_socket_order();
162 const bNodeTree *tree = b.tree_or_null();
163 const bNode *node = b.node_or_null();
164 if (node) {
165 const NodeGeometryRepeatOutput &storage = node_storage(*node);
166 for (const int i : IndexRange(storage.items_num)) {
167 const NodeRepeatItem &item = storage.items[i];
168 const eNodeSocketDatatype socket_type = eNodeSocketDatatype(item.socket_type);
169 const StringRef name = item.name ? item.name : "";
170 const std::string identifier = RepeatItemsAccessor::socket_identifier_for_item(item);
171 auto &input_decl = b.add_input(socket_type, name, identifier)
172 .socket_name_ptr(
173 &tree->id, RepeatItemsAccessor::item_srna, &item, "name");
174 auto &output_decl = b.add_output(socket_type, name, identifier).align_with_previous();
175 if (socket_type_supports_fields(socket_type)) {
176 input_decl.supports_field();
177 output_decl.dependent_field({input_decl.index()});
178 }
179 }
180 }
181 b.add_input<decl::Extend>("", "__extend__").structure_type(StructureType::Dynamic);
182 b.add_output<decl::Extend>("", "__extend__")
183 .structure_type(StructureType::Dynamic)
184 .align_with_previous();
185}
186
187static void node_init(bNodeTree * /*tree*/, bNode *node)
188{
190
191 data->next_identifier = 0;
192
193 data->items = MEM_calloc_arrayN<NodeRepeatItem>(1, __func__);
194 data->items[0].name = BLI_strdup(DATA_("Geometry"));
195 data->items[0].socket_type = SOCK_GEOMETRY;
196 data->items[0].identifier = data->next_identifier++;
197 data->items_num = 1;
198
199 node->storage = data;
200}
201
207
208static void node_copy_storage(bNodeTree * /*dst_tree*/, bNode *dst_node, const bNode *src_node)
209{
210 const NodeGeometryRepeatOutput &src_storage = node_storage(*src_node);
211 auto *dst_storage = MEM_dupallocN<NodeGeometryRepeatOutput>(__func__, src_storage);
212 dst_node->storage = dst_storage;
213
215}
216
217static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
218{
220 *ntree, *node, *node, *link);
221}
222
227
229{
230 const bNodeSocket &other_socket = params.other_socket();
232 return;
233 }
234 params.add_item_full_name(IFACE_("Repeat"), [](LinkSearchOpParams &params) {
235 bNode &input_node = params.add_node("GeometryNodeRepeatInput");
236 bNode &output_node = params.add_node("GeometryNodeRepeatOutput");
237 output_node.location[0] = 300;
238
239 auto &input_storage = *static_cast<NodeGeometryRepeatInput *>(input_node.storage);
240 input_storage.output_node_id = output_node.identifier;
241
244 output_node, eNodeSocketDatatype(params.socket.type), params.socket.name);
245 update_node_declaration_and_sockets(params.node_tree, input_node);
246 update_node_declaration_and_sockets(params.node_tree, output_node);
247 if (params.socket.in_out == SOCK_IN) {
248 params.connect_available_socket(output_node, params.socket.name);
249 }
250 else {
251 params.connect_available_socket(input_node, params.socket.name);
252 }
253 params.node_tree.ensure_topology_cache();
254 bke::node_add_link(params.node_tree,
255 input_node,
256 input_node.output_socket(1),
257 output_node,
258 output_node.input_socket(0));
259 });
260}
261
262static void node_blend_write(const bNodeTree & /*tree*/, const bNode &node, BlendWriter &writer)
263{
265}
266
267static void node_blend_read(bNodeTree & /*tree*/, bNode &node, BlendDataReader &reader)
268{
270}
271
272static void node_register()
273{
274 static blender::bke::bNodeType ntype;
275 geo_node_type_base(&ntype, "GeometryNodeRepeatOutput", GEO_NODE_REPEAT_OUTPUT);
276 ntype.ui_name = "Repeat Output";
277 ntype.enum_name_legacy = "REPEAT_OUTPUT";
279 ntype.initfunc = node_init;
280 ntype.declare = node_declare;
284 ntype.no_muting = true;
290 ntype, "NodeGeometryRepeatOutput", node_free_storage, node_copy_storage);
292}
294
295} // namespace repeat_output_node
296
297} // namespace blender::nodes::node_geo_repeat_cc
298
299namespace blender::nodes {
300
302
304{
305 BLO_write_string(writer, item.name);
306}
307
309{
310 BLO_read_string(reader, &item.name);
311}
312
313} // namespace blender::nodes
314
315blender::Span<NodeRepeatItem> NodeGeometryRepeatOutput::items_span() const
316{
317 return blender::Span<NodeRepeatItem>(items, items_num);
318}
319
320blender::MutableSpan<NodeRepeatItem> NodeGeometryRepeatOutput::items_span()
321{
322 return blender::MutableSpan<NodeRepeatItem>(items, items_num);
323}
#define NODE_CLASS_INTERFACE
Definition BKE_node.hh:445
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1215
#define GEO_NODE_REPEAT_OUTPUT
#define GEO_NODE_REPEAT_INPUT
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
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:5351
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define IFACE_(msgid)
#define DATA_(msgid)
@ SOCK_IN
eNodeSocketDatatype
@ SOCK_GEOMETRY
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define C
Definition RandGen.cpp:29
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
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
KDTree_3d * tree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:4087
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))
Definition node.cc:5603
static void node_init(bNodeTree *, bNode *node)
static void node_label(const bNodeTree *, const bNode *, char *label, const int label_maxncpy)
static void node_declare(NodeDeclarationBuilder &b)
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 void node_blend_read(bNodeTree &, bNode &node, BlendDataReader &reader)
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
static void node_blend_write(const bNodeTree &, const bNode &node, BlendWriter &writer)
static void node_declare(NodeDeclarationBuilder &b)
static void node_init(bNodeTree *, bNode *node)
static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *current_node_ptr)
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 blend_read_data(BlendDataReader *reader, bNode &node)
void copy_array(const bNode &src_node, bNode &dst_node)
Accessor::ItemT * add_item_with_socket_type_and_name(bNode &node, const eNodeSocketDatatype socket_type, const char *name)
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 update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
bool socket_type_supports_fields(const eNodeSocketDatatype socket_type)
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)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
#define min(a, b)
Definition sort.cc:36
ID * owner_id
Definition RNA_types.hh:51
void * data
Definition RNA_types.hh:53
float location[2]
void * storage
int32_t identifier
Defines a node type.
Definition BKE_node.hh:226
NodeBlendWriteFunction blend_write_storage_content
Definition BKE_node.hh:383
NodeBlendDataReadFunction blend_data_read_storage_content
Definition BKE_node.hh:384
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:277
void(* labelfunc)(const bNodeTree *ntree, const bNode *node, char *label, int label_maxncpy)
Definition BKE_node.hh:258
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:249
const char * enum_name_legacy
Definition BKE_node.hh:235
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:371
bool(* insert_link)(bNodeTree *ntree, bNode *node, bNodeLink *link)
Definition BKE_node.hh:321
NodeDeclareFunction declare
Definition BKE_node.hh:355
void(* register_operators)()
Definition BKE_node.hh:410
static void blend_write_item(BlendWriter *writer, const ItemT &item)
static bool supports_socket_type(const eNodeSocketDatatype socket_type)
static void blend_read_data_item(BlendDataReader *reader, ItemT &item)
static std::string socket_identifier_for_item(const NodeRepeatItem &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)
i
Definition text_draw.cc:230