42 if (typeinfo ==
nullptr) {
139 static float default_value[] = {0.0f, 0.0f, 0.0f};
148 static float default_value[] = {0.0f, 0.0f, 0.0f, 1.0f};
154 data.value[0] =
'\0';
158 data.value =
nullptr;
162 data.value =
nullptr;
166 data.value =
nullptr;
170 data.value =
nullptr;
174 data.value =
nullptr;
179 data.enum_items =
nullptr;
180 data.runtime_flag = 0;
185 void *socket_data =
nullptr;
187 using SocketDataType =
typename decltype(type_tag)::type;
190 socket_data = new_socket_data;
206 dst.
enum_items->remove_user_and_delete_if_last();
213 using SocketDataType = typename decltype(type_tag)::type;
215 socket_data_id_user_decrement(get_socket_data_as<SocketDataType>(socket));
242 using SocketDataType = typename decltype(type_tag)::type;
243 dst.socket_data = MEM_dupallocN(src.socket_data);
244 socket_data_copy_impl(get_socket_data_as<SocketDataType>(dst),
245 get_socket_data_as<SocketDataType>(src));
246 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
247 socket_data_id_user_increment(get_socket_data_as<SocketDataType>(dst));
254 const void *src_socket_data,
258 using SocketDataType = typename decltype(type_tag)::type;
260 if (dst.socket_data != nullptr) {
261 socket_data_free(dst, true);
262 MEM_SAFE_FREE(dst.socket_data);
267 *
static_cast<const SocketDataType *
>(src_socket_data));
338 using SocketDataType = typename decltype(type_tag)::type;
339 socket_data_write_impl(writer, get_socket_data_as<SocketDataType>(socket));
361 (*data)->enum_items =
nullptr;
362 (*data)->runtime_flag = 0;
367 bool data_read =
false;
369 using SocketDataType = typename decltype(type_tag)::type;
370 socket_data_read_data_impl(reader, reinterpret_cast<SocketDataType **>(&socket.socket_data));
416 using SocketDataType = typename decltype(type_tag)::type;
417 socket_data_foreach_id_impl(data, get_socket_data_as<SocketDataType>(socket));
526 panel.clear(do_id_user);
650 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
675 return panel.items();
703bool bNodeTreeInterfaceSocket::set_socket_type(
const StringRef new_socket_type)
720 blender::bke::bNodeSocketType *stype = this->socket_typeinfo();
730void bNodeTreeInterfaceSocket::init_from_socket_instance(
const bNodeSocket *socket)
767 return items().contains(&
item);
777 if (&titem == &
item) {
789 return items().first_index_try(&
item);
799 if (&titem == &
item) {
806 return found ? index : -1;
827 std::queue<bNodeTreeInterfacePanel *> queue;
829 if (this->contains(
item)) {
834 while (!queue.empty()) {
844 if (tpanel->contains(
item)) {
854int bNodeTreeInterfacePanel::find_valid_insert_position_for_item(
857 const bool sockets_above_panels = !(this->
flag &
859 const blender::Span<const bNodeTreeInterfaceItem *> items = this->items();
865 if (sockets_above_panels) {
882 if (is_output_a && !is_output_b) {
891 if (must_be_before(*items[
i],
item)) {
895 int max_pos = items.
size();
897 if (must_be_before(
item, *items[
i])) {
903 return std::clamp(initial_pos, min_pos, max_pos);
915 position = find_valid_insert_position_for_item(
item, position);
916 position = std::min(std::max(position, 0),
items_num);
918 blender::MutableSpan<bNodeTreeInterfaceItem *> old_items = this->items();
923 this->items()[position] = &
item;
925 if (old_items.
data()) {
932 const int position = this->item_position(
item);
933 if (!this->items().index_range().contains(position)) {
937 blender::MutableSpan<bNodeTreeInterfaceItem *> old_items = this->items();
953void bNodeTreeInterfacePanel::clear(
bool do_id_user)
965 const int old_position = this->item_position(
item);
966 if (!this->items().index_range().contains(old_position)) {
969 if (old_position == new_position) {
974 new_position = find_valid_insert_position_for_item(
item, new_position);
975 new_position = std::min(std::max(new_position, 0),
items_num);
977 if (old_position < new_position) {
979 const blender::Span<bNodeTreeInterfaceItem *> moved_items = this->items().
slice(
980 old_position + 1, new_position - old_position - 1);
983 moved_items.
begin(), moved_items.
end(),
this->items().drop_front(old_position).data());
984 this->items()[new_position - 1] = tmp;
987 const blender::Span<bNodeTreeInterfaceItem *> moved_items = this->items().
slice(
988 new_position, old_position - new_position);
991 moved_items.
begin(), moved_items.
end(),
this->items().drop_front(old_position + 1).data());
992 this->items()[new_position] = tmp;
998void bNodeTreeInterfacePanel::foreach_item(
1001 using ItemSpan = blender::Span<bNodeTreeInterfaceItem *>;
1002 blender::Stack<ItemSpan> stack;
1004 if (include_self && fn(this->
item) ==
false) {
1007 stack.
push(this->items());
1010 const ItemSpan current_items = stack.
pop();
1012 for (
const int index : current_items.index_range()) {
1014 if (fn(*
item) ==
false) {
1021 if (index < current_items.size() - 1) {
1022 const ItemSpan remaining_items = current_items.drop_front(index + 1);
1023 stack.
push(remaining_items);
1026 stack.
push(panel->items());
1033void bNodeTreeInterfacePanel::foreach_item(
1036 using ItemSpan = blender::Span<const bNodeTreeInterfaceItem *>;
1037 blender::Stack<ItemSpan> stack;
1039 if (include_self && fn(this->
item) ==
false) {
1042 stack.
push(this->items());
1045 const ItemSpan current_items = stack.
pop();
1047 for (
const int index : current_items.index_range()) {
1049 if (fn(*
item) ==
false) {
1057 if (index < current_items.size() - 1) {
1058 const ItemSpan remaining_items = current_items.drop_front(index + 1);
1059 stack.
push(remaining_items);
1062 stack.
push(panel->items());
1071 if (this->items().is_empty()) {
1084 const blender::bke::bNodeSocketType *typeinfo = socket.socket_typeinfo();
1130 const bNode &from_node,
1135 ntree.ensure_topology_cache();
1137 if (from_node.is_group()) {
1140 group->ensure_interface_cache();
1142 from_sock.is_input() ? *group->interface_inputs()[from_sock.index()] :
1143 *group->interface_outputs()[from_sock.index()];
1161 iosock = ntree.
tree_interface.add_socket(name, description, socket_type,
flag,
nullptr);
1169 if (iosock ==
nullptr) {
1199void bNodeTreeInterface::init_data()
1201 this->
runtime = MEM_new<blender::bke::bNodeTreeInterfaceRuntime>(__func__);
1202 this->tag_missing_runtime_data();
1210 this->
runtime = MEM_new<blender::bke::bNodeTreeInterfaceRuntime>(__func__);
1211 this->tag_missing_runtime_data();
1214void bNodeTreeInterface::free_data()
1222void bNodeTreeInterface::write(
BlendWriter *writer)
1232 this->
runtime = MEM_new<blender::bke::bNodeTreeInterfaceRuntime>(__func__);
1233 this->tag_missing_runtime_data();
1271 if (&titem == item) {
1290 if (parent ==
nullptr) {
1296 this->
next_uid++, name, description, socket_type,
flag);
1298 parent->add_item(new_socket->
item);
1301 this->tag_items_changed();
1312 if (parent ==
nullptr) {
1318 this->
next_uid++, name, description, socket_type,
flag);
1320 parent->insert_item(new_socket->
item, position);
1323 this->tag_items_changed();
1332 if (parent ==
nullptr) {
1339 parent->add_item(new_panel->
item);
1342 this->tag_items_changed();
1352 if (parent ==
nullptr) {
1359 parent->insert_item(new_panel->
item, position);
1362 this->tag_items_changed();
1369 if (parent ==
nullptr) {
1376 parent->add_item(*citem);
1378 this->tag_items_changed();
1386 if (parent ==
nullptr) {
1394 parent->insert_item(*citem, position);
1396 this->tag_items_changed();
1403 if (parent ==
nullptr) {
1406 if (move_content_to_parent) {
1407 int position = parent->item_position(item);
1411 this->move_item_to_parent(*child, parent, position++);
1414 if (parent->remove_item(item,
true)) {
1415 this->tag_items_changed();
1422void bNodeTreeInterface::clear_items()
1425 this->tag_items_changed();
1431 if (parent ==
nullptr) {
1435 if (parent->move_item(item, new_position)) {
1436 this->tag_items_changed();
1446 if (new_parent ==
nullptr) {
1452 if (src_item.contains_recursive(new_parent->
item)) {
1458 if (parent ==
nullptr) {
1462 if (parent == new_parent) {
1463 if (parent->move_item(item, new_position)) {
1464 this->tag_items_changed();
1471 if (parent->remove_item(item,
false)) {
1472 new_parent->insert_item(item, new_position);
1473 this->tag_items_changed();
1485bool bNodeTreeInterface::items_cache_is_available()
const
1487 return !this->
runtime->items_cache_mutex_.is_dirty();
1490void bNodeTreeInterface::ensure_items_cache()
const
1492 blender::bke::bNodeTreeInterfaceRuntime &
runtime = *this->
runtime;
1494 runtime.items_cache_mutex_.ensure([&]() {
1506 runtime.items_.add_new(&item);
1509 runtime.inputs_.add_new(socket);
1512 runtime.outputs_.add_new(socket);
1520void bNodeTreeInterface::tag_interface_changed()
1522 this->
runtime->interface_changed_.store(
true);
1525bool bNodeTreeInterface::requires_dependent_tree_updates()
const
1527 return this->
runtime->interface_changed_.load(std::memory_order_relaxed);
1530void bNodeTreeInterface::tag_items_changed()
1532 this->tag_interface_changed();
1533 this->
runtime->items_cache_mutex_.tag_dirty();
1536void bNodeTreeInterface::tag_items_changed_generic()
1539 this->tag_items_changed();
1542void bNodeTreeInterface::tag_item_property_changed()
1544 this->tag_interface_changed();
1547void bNodeTreeInterface::tag_missing_runtime_data()
1549 this->tag_items_changed();
1552void bNodeTreeInterface::reset_interface_changed()
1554 this->
runtime->interface_changed_.store(
false);
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
#define IDP_BlendDataRead(reader, prop)
void IDP_FreePropertyContent_ex(IDProperty *prop, bool do_id_user)
IDProperty * IDP_CopyProperty_ex(const IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
@ LIB_ID_CREATE_NO_USER_REFCOUNT
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data_, func_call_)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
void BLI_kdtree_nd_ free(KDTree *tree)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
char * BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
#define SET_FLAG_FROM_TEST(value, test, flag)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define BLO_read_struct(reader, struct_name, ptr_p)
void BLO_write_pointer_array(BlendWriter *writer, int64_t num, const void *data_ptr)
void BLO_read_pointer_array(BlendDataReader *reader, int64_t array_size, void **ptr_p)
Object groups, one object can be in many groups at once.
NodeTreeInterfaceItemType
NodeTreeInterfacePanelFlag
@ NODE_INTERFACE_PANEL_ALLOW_SOCKETS_AFTER_PANELS
NodeTreeInterfaceSocketFlag
@ NODE_INTERFACE_SOCKET_SINGLE_VALUE_ONLY_LEGACY
@ NODE_INTERFACE_SOCKET_OUTPUT
@ NODE_INTERFACE_SOCKET_PANEL_TOGGLE
@ NODE_INTERFACE_SOCKET_INPUT
@ NODE_INTERFACE_SOCKET_HIDE_VALUE
struct bNodeTreeInterface bNodeTreeInterface
struct bNodeTreeInterfaceSocket bNodeTreeInterfaceSocket
@ NODE_DEFAULT_INPUT_VALUE
struct bNodeTreeInterfacePanel bNodeTreeInterfacePanel
@ NODE_INTERFACE_SOCKET_STRUCTURE_TYPE_SINGLE
struct bNodeTreeInterfaceItem bNodeTreeInterfaceItem
BMesh const char void * data
constexpr T * data() const
constexpr MutableSpan drop_front(const int64_t n) const
constexpr MutableSpan take_front(const int64_t n) const
constexpr Span drop_front(int64_t n) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T & first() const
constexpr int64_t size() const
constexpr const T * end() const
constexpr IndexRange index_range() const
constexpr const T * begin() const
constexpr Span take_front(int64_t n) const
void push(const T &value)
constexpr bool is_empty() const
constexpr int64_t size() const
constexpr const char * data() const
NodeDefaultInputType default_input_type
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 item_write_struct(BlendWriter *writer, bNodeTreeInterfaceItem &item)
static void item_copy(bNodeTreeInterfaceItem &dst, const bNodeTreeInterfaceItem &src, int flag, UidGeneratorFn generate_uid)
static void item_free(bNodeTreeInterfaceItem &item, const bool do_id_user)
blender::FunctionRef< int()> UidGeneratorFn
static void item_write_data(BlendWriter *writer, bNodeTreeInterfaceItem &item)
static Span< bNodeTreeInterfaceItem * > item_children(bNodeTreeInterfaceItem &item)
static void item_read_data(BlendDataReader *reader, bNodeTreeInterfaceItem &item)
static void item_foreach_id(LibraryForeachIDData *data, bNodeTreeInterfaceItem &item)
static void panel_init(bNodeTreeInterfacePanel &panel, const Span< const bNodeTreeInterfaceItem * > items_src, const int flag, UidGeneratorFn generate_uid)
static std::optional< StringRef > try_get_supported_socket_type(const StringRef socket_type)
static void socket_data_read_data(BlendDataReader *reader, bNodeTreeInterfaceSocket &socket)
void socket_data_foreach_id_impl(LibraryForeachIDData *, T &)
static void * make_socket_data(const StringRef socket_type)
void socket_data_id_user_decrement(T &)
void socket_data_copy_impl(T &, const T &)
void socket_data_free_impl(T &, const bool)
static void socket_data_free(bNodeTreeInterfaceSocket &socket, const bool do_id_user)
void socket_data_to_static_type_tag(const StringRef socket_type, const Fn &fn)
static void socket_data_write(BlendWriter *writer, bNodeTreeInterfaceSocket &socket)
static void socket_data_foreach_id(LibraryForeachIDData *data, bNodeTreeInterfaceSocket &socket)
void socket_data_id_user_increment(T &)
void socket_data_init_impl(T &)
static void socket_data_copy(bNodeTreeInterfaceSocket &dst, const bNodeTreeInterfaceSocket &src, int flag)
static void socket_data_copy_ptr(bNodeTreeInterfaceSocket &dst, const void *src_socket_data, int flag)
void socket_data_write_impl(BlendWriter *writer, bNodeSocketValueFloat &data)
void socket_data_read_data_impl(BlendDataReader *reader, T **data)
T & get_item_as(bNodeTreeInterfaceItem &item)
static bNodeTreeInterfaceSocket * make_socket(const int uid, const StringRef name, const StringRef description, const StringRef socket_type, const NodeTreeInterfaceSocketFlag flag)
bNodeTreeInterfaceSocket * add_interface_socket_from_node(bNodeTree &ntree, const bNode &from_node, const bNodeSocket &from_sock, StringRef socket_type, StringRef name)
static bNodeTreeInterfacePanel * make_panel(const int uid, const blender::StringRef name, const blender::StringRef description, const NodeTreeInterfacePanelFlag flag)
T & get_socket_data_as(bNodeTreeInterfaceSocket &item)
bNodeSocketType * node_socket_type_find(StringRef idname)
std::optional< StringRefNull > node_static_socket_type(int type, int subtype, std::optional< int > dimensions=std::nullopt)
bool node_is_static_socket_type(const bNodeSocketType &stype)
bool socket_type_supports_default_input_type(const bke::bNodeSocketType &socket_type, const NodeDefaultInputType input_type)
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
static bool is_child(const Object *ob, const Object *parent)
bNodeSocketRuntimeHandle * runtime
bNodeTreeInterfaceItem ** items_array
bNodeTreeInterfaceItem item
struct IDProperty * properties
bNodeTreeInterfaceItem item
char * default_attribute_name
bNodeTreeInterfacePanel root_panel
bNodeTreeInterfaceRuntimeHandle * runtime
bNodeTreeInterface tree_interface
void(* draw_color_simple)(const bNodeSocketType *socket_type, float *r_color)
void(* interface_from_socket)(ID *id, bNodeTreeInterfaceSocket *interface_socket, const bNode *node, const bNodeSocket *socket)