43 if (typeinfo ==
nullptr) {
140 static float default_value[] = {0.0f, 0.0f, 0.0f};
149 static float default_value[] = {0.0f, 0.0f, 0.0f, 1.0f};
155 data.value[0] =
'\0';
159 data.value =
nullptr;
163 data.value =
nullptr;
167 data.value =
nullptr;
171 data.value =
nullptr;
175 data.value =
nullptr;
180 data.enum_items =
nullptr;
181 data.runtime_flag = 0;
186 void *socket_data =
nullptr;
188 using SocketDataType =
typename decltype(type_tag)::type;
191 socket_data = new_socket_data;
207 dst.
enum_items->remove_user_and_delete_if_last();
214 using SocketDataType = typename decltype(type_tag)::type;
216 socket_data_id_user_decrement(get_socket_data_as<SocketDataType>(socket));
243 using SocketDataType = typename decltype(type_tag)::type;
244 dst.socket_data = MEM_dupallocN(src.socket_data);
245 socket_data_copy_impl(get_socket_data_as<SocketDataType>(dst),
246 get_socket_data_as<SocketDataType>(src));
247 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
248 socket_data_id_user_increment(get_socket_data_as<SocketDataType>(dst));
255 const void *src_socket_data,
259 using SocketDataType = typename decltype(type_tag)::type;
261 if (dst.socket_data != nullptr) {
262 socket_data_free(dst, true);
263 MEM_SAFE_FREE(dst.socket_data);
268 *
static_cast<const SocketDataType *
>(src_socket_data));
339 using SocketDataType = typename decltype(type_tag)::type;
340 socket_data_write_impl(writer, get_socket_data_as<SocketDataType>(socket));
362 (*data)->enum_items =
nullptr;
363 (*data)->runtime_flag = 0;
368 bool data_read =
false;
370 using SocketDataType = typename decltype(type_tag)::type;
371 socket_data_read_data_impl(reader, reinterpret_cast<SocketDataType **>(&socket.socket_data));
417 using SocketDataType = typename decltype(type_tag)::type;
418 socket_data_foreach_id_impl(data, get_socket_data_as<SocketDataType>(socket));
527 panel.clear(do_id_user);
651 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
676 return panel.items();
704bool bNodeTreeInterfaceSocket::set_socket_type(
const StringRef new_socket_type)
721 blender::bke::bNodeSocketType *stype = this->socket_typeinfo();
731void bNodeTreeInterfaceSocket::init_from_socket_instance(
const bNodeSocket *socket)
768 return items().contains(&
item);
778 if (&titem == &
item) {
790 return items().first_index_try(&
item);
800 if (&titem == &
item) {
807 return found ? index : -1;
828 std::queue<bNodeTreeInterfacePanel *> queue;
835 while (!queue.empty()) {
845 if (tpanel->contains(
item)) {
855int bNodeTreeInterfacePanel::find_valid_insert_position_for_item(
858 const bool sockets_above_panels = !(this->
flag &
860 const blender::Span<const bNodeTreeInterfaceItem *> items = this->items();
866 if (sockets_above_panels) {
883 if (is_output_a && !is_output_b) {
892 if (must_be_before(*items[
i],
item)) {
896 int max_pos = items.
size();
898 if (must_be_before(
item, *items[
i])) {
904 return std::clamp(initial_pos, min_pos, max_pos);
916 position = find_valid_insert_position_for_item(
item, position);
917 position = std::min(std::max(position, 0),
items_num);
919 blender::MutableSpan<bNodeTreeInterfaceItem *> old_items = this->items();
924 this->items()[position] = &
item;
926 if (old_items.
data()) {
933 const int position = this->item_position(
item);
934 if (!this->items().index_range().
contains(position)) {
938 blender::MutableSpan<bNodeTreeInterfaceItem *> old_items = this->items();
954void bNodeTreeInterfacePanel::clear(
bool do_id_user)
966 const int old_position = this->item_position(
item);
967 if (!this->items().index_range().
contains(old_position)) {
970 if (old_position == new_position) {
975 new_position = find_valid_insert_position_for_item(
item, new_position);
976 new_position = std::min(std::max(new_position, 0),
items_num);
978 if (old_position < new_position) {
980 const blender::Span<bNodeTreeInterfaceItem *> moved_items = this->items().
slice(
981 old_position + 1, new_position - old_position - 1);
984 moved_items.
begin(), moved_items.
end(), this->items().drop_front(old_position).data());
985 this->items()[new_position - 1] = tmp;
988 const blender::Span<bNodeTreeInterfaceItem *> moved_items = this->items().
slice(
989 new_position, old_position - new_position);
992 moved_items.
begin(), moved_items.
end(), this->items().drop_front(old_position + 1).data());
993 this->items()[new_position] = tmp;
999void bNodeTreeInterfacePanel::foreach_item(
1002 using ItemSpan = blender::Span<bNodeTreeInterfaceItem *>;
1003 blender::Stack<ItemSpan> stack;
1005 if (include_self && fn(this->
item) ==
false) {
1008 stack.
push(this->items());
1011 const ItemSpan current_items = stack.
pop();
1013 for (
const int index : current_items.index_range()) {
1015 if (fn(*
item) ==
false) {
1022 if (index < current_items.size() - 1) {
1023 const ItemSpan remaining_items = current_items.drop_front(index + 1);
1024 stack.
push(remaining_items);
1027 stack.
push(panel->items());
1034void bNodeTreeInterfacePanel::foreach_item(
1037 using ItemSpan = blender::Span<const bNodeTreeInterfaceItem *>;
1038 blender::Stack<ItemSpan> stack;
1040 if (include_self && fn(this->
item) ==
false) {
1043 stack.
push(this->items());
1046 const ItemSpan current_items = stack.
pop();
1048 for (
const int index : current_items.index_range()) {
1050 if (fn(*
item) ==
false) {
1058 if (index < current_items.size() - 1) {
1059 const ItemSpan remaining_items = current_items.drop_front(index + 1);
1060 stack.
push(remaining_items);
1063 stack.
push(panel->items());
1072 if (this->items().is_empty()) {
1085 const blender::bke::bNodeSocketType *typeinfo = socket.socket_typeinfo();
1131 const bNode &from_node,
1136 ntree.ensure_topology_cache();
1138 if (from_node.is_group()) {
1141 group->ensure_interface_cache();
1143 from_sock.is_input() ? *group->interface_inputs()[from_sock.index()] :
1144 *group->interface_outputs()[from_sock.index()];
1161 if (socket_type ==
"NodeSocketMenu" && from_sock.
type ==
SOCK_MENU) {
1176 if (iosock ==
nullptr) {
1206void bNodeTreeInterface::init_data()
1208 this->
runtime = MEM_new<blender::bke::bNodeTreeInterfaceRuntime>(__func__);
1209 this->tag_missing_runtime_data();
1217 this->
runtime = MEM_new<blender::bke::bNodeTreeInterfaceRuntime>(__func__);
1218 this->tag_missing_runtime_data();
1221void bNodeTreeInterface::free_data()
1229void bNodeTreeInterface::write(
BlendWriter *writer)
1239 this->
runtime = MEM_new<blender::bke::bNodeTreeInterfaceRuntime>(__func__);
1240 this->tag_missing_runtime_data();
1278 if (&titem == item) {
1297 if (parent ==
nullptr) {
1305 parent->add_item(new_socket->
item);
1308 this->tag_items_changed();
1319 if (parent ==
nullptr) {
1327 parent->insert_item(new_socket->
item, position);
1330 this->tag_items_changed();
1339 if (parent ==
nullptr) {
1346 parent->add_item(new_panel->
item);
1349 this->tag_items_changed();
1359 if (parent ==
nullptr) {
1366 parent->insert_item(new_panel->
item, position);
1369 this->tag_items_changed();
1376 if (parent ==
nullptr) {
1383 parent->add_item(*citem);
1385 this->tag_items_changed();
1393 if (parent ==
nullptr) {
1401 parent->insert_item(*citem, position);
1403 this->tag_items_changed();
1410 if (parent ==
nullptr) {
1413 if (move_content_to_parent) {
1414 int position = parent->item_position(item);
1418 this->move_item_to_parent(*child, parent, position++);
1421 if (parent->remove_item(item,
true)) {
1422 this->tag_items_changed();
1429void bNodeTreeInterface::clear_items()
1432 this->tag_items_changed();
1438 if (parent ==
nullptr) {
1442 if (parent->move_item(item, new_position)) {
1443 this->tag_items_changed();
1453 if (new_parent ==
nullptr) {
1459 if (src_item.contains_recursive(new_parent->
item)) {
1465 if (parent ==
nullptr) {
1469 if (parent == new_parent) {
1470 if (parent->move_item(item, new_position)) {
1471 this->tag_items_changed();
1478 if (parent->remove_item(item,
false)) {
1479 new_parent->insert_item(item, new_position);
1480 this->tag_items_changed();
1492bool bNodeTreeInterface::items_cache_is_available()
const
1494 return !this->
runtime->items_cache_mutex_.is_dirty();
1497void bNodeTreeInterface::ensure_items_cache()
const
1499 blender::bke::bNodeTreeInterfaceRuntime &
runtime = *this->
runtime;
1501 runtime.items_cache_mutex_.ensure([&]() {
1513 runtime.items_.add_new(&item);
1516 runtime.inputs_.add_new(socket);
1519 runtime.outputs_.add_new(socket);
1527void bNodeTreeInterface::tag_interface_changed()
1529 this->
runtime->interface_changed_.store(
true);
1532bool bNodeTreeInterface::requires_dependent_tree_updates()
const
1534 return this->
runtime->interface_changed_.load(std::memory_order_relaxed);
1537void bNodeTreeInterface::tag_items_changed()
1539 this->tag_interface_changed();
1540 this->
runtime->items_cache_mutex_.tag_dirty();
1543void bNodeTreeInterface::tag_items_changed_generic()
1546 this->tag_items_changed();
1549void bNodeTreeInterface::tag_item_property_changed()
1551 this->tag_interface_changed();
1554void bNodeTreeInterface::tag_missing_runtime_data()
1556 this->tag_items_changed();
1559void bNodeTreeInterface::reset_interface_changed()
1561 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_OPTIONAL_LABEL
@ NODE_INTERFACE_SOCKET_MENU_EXPANDED
@ 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)
bool contains(const VArray< bool > &varray, const IndexMask &indices_to_check, bool value)
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)