45template<
typename Accessor>
48 ntree.ensure_topology_cache();
49 for (
bNode *node : ntree.nodes_by_type(Accessor::node_idname)) {
63 using ItemT =
typename Accessor::ItemT;
66 ItemT &item = (*ref.
items)[i];
67 Accessor::destruct_item(&item);
77 using ItemT =
typename Accessor::ItemT;
81 *dst_ref.
items = MEM_cnew_array<ItemT>(items_num, __func__);
83 Accessor::copy_item((*src_ref.
items)[i], (*dst_ref.
items)[i]);
91template<
typename Accessor>
93 typename Accessor::ItemT &item,
96 using ItemT =
typename Accessor::ItemT;
98 const char *default_name =
"Item";
99 if constexpr (Accessor::has_type) {
109 } args = {
array, &item};
111 [](
void *arg,
const char *name) {
112 const Args &args = *
static_cast<Args *
>(arg);
114 if (&item != args.item) {
115 if (
STREQ(*Accessor::get_name(item), name)) {
128 char **item_name = Accessor::get_name(item);
137 using ItemT =
typename Accessor::ItemT;
140 ItemT *old_items = *
array.items;
141 const int old_items_num = *
array.items_num;
142 const int new_items_num = old_items_num + 1;
144 ItemT *new_items = MEM_cnew_array<ItemT>(new_items_num, __func__);
145 std::copy_n(old_items, old_items_num, new_items);
146 ItemT &new_item = new_items[old_items_num];
149 *
array.items = new_items;
150 *
array.items_num = new_items_num;
151 if (
array.active_index) {
152 *
array.active_index = old_items_num;
163template<
typename Accessor>
167 using ItemT =
typename Accessor::ItemT;
168 BLI_assert(Accessor::supports_socket_type(socket_type));
170 Accessor::init_with_socket_type_and_name(node, new_item, socket_type, name);
177template<
typename Accessor>
180 using ItemT =
typename Accessor::ItemT;
182 Accessor::init_with_name(node, new_item, name);
189template<
typename Accessor>
inline typename Accessor::ItemT *
add_item(
bNode &node)
191 using ItemT =
typename Accessor::ItemT;
193 Accessor::init(node, new_item);
197template<
typename Accessor>
201 if constexpr (Accessor::has_single_identifier_str) {
202 return Accessor::socket_identifier_for_item(item);
206 return Accessor::input_socket_identifier_for_item(item);
209 return Accessor::output_socket_identifier_for_item(item);
219template<
typename Accessor>
226 using ItemT =
typename Accessor::ItemT;
228 if (link.
tosock == &extend_socket) {
231 else if (link.
fromsock == &extend_socket) {
238 const ItemT *item =
nullptr;
239 if constexpr (Accessor::has_name && Accessor::has_type) {
241 if (!Accessor::supports_socket_type(socket_type)) {
245 storage_node, socket_type, src_socket->
name);
247 else if constexpr (Accessor::has_name && !Accessor::has_type) {
253 if (item ==
nullptr) {
258 if (extend_socket.is_input()) {
261 &extend_node,
SOCK_IN, item_identifier.c_str());
267 &extend_node,
SOCK_OUT, item_identifier.c_str());
277template<
typename Accessor>
283 const std::optional<StringRef> socket_identifier = std::nullopt)
286 if (link.
fromnode == &extend_node) {
287 possible_extend_socket = link.
fromsock;
289 if (link.
tonode == &extend_node) {
290 possible_extend_socket = link.
tosock;
292 if (possible_extend_socket ==
nullptr) {
295 if (!
STREQ(possible_extend_socket->
idname,
"NodeSocketVirtual")) {
298 if (socket_identifier.has_value()) {
299 if (possible_extend_socket->
identifier != socket_identifier) {
304 ntree, extend_node, *possible_extend_socket, storage_node, link);
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
#define STRNCPY(dst, src)
size_t void BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_maxncpy) ATTR_NONNULL(1
const char * node_static_socket_label(int type, int subtype)
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Accessor::ItemT & add_item_to_array(bNode &node)
void set_item_name_and_make_unique(bNode &node, typename Accessor::ItemT &item, const char *value)
Accessor::ItemT * add_item_with_name(bNode &node, const char *name)
void destruct_array(bNode &node)
Accessor::ItemT * add_item(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)
bool try_add_item_via_extend_socket(bNodeTree &ntree, bNode &extend_node, bNodeSocket &extend_socket, bNode &storage_node, bNodeLink &link)
bNode * find_node_by_item(bNodeTree &ntree, const typename Accessor::ItemT &item)
std::string get_socket_identifier(const typename Accessor::ItemT &item, const eNodeSocketInOut in_out)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
static void unique_name(bNode *node)