/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "DNA_node_tree_interface_types.h" #include "DNA_node_types.h" #include "BKE_node.h" #include #include #include "BLI_parameter_pack_utils.hh" #include "BLI_vector.hh" namespace blender::bke { /* Runtime topology cache for linear access to items. */ struct bNodeTreeInterfaceCache { Vector items; Vector inputs; Vector outputs; void rebuild(bNodeTreeInterface &tree_interface); }; namespace node_interface { namespace detail { template static bool item_is_type(const bNodeTreeInterfaceItem &item) { bool match = false; switch (item.item_type) { case NODE_INTERFACE_SOCKET: { match |= std::is_same::value; break; } case NODE_INTERFACE_PANEL: { match |= std::is_same::value; break; } } return match; } } // namespace detail template T &get_item_as(bNodeTreeInterfaceItem &item) { BLI_assert(detail::item_is_type(item)); return reinterpret_cast(item); } template const T &get_item_as(const bNodeTreeInterfaceItem &item) { BLI_assert(detail::item_is_type(item)); return reinterpret_cast(item); } template T *get_item_as(bNodeTreeInterfaceItem *item) { if (item && detail::item_is_type(*item)) { return reinterpret_cast(item); } return nullptr; } template const T *get_item_as(const bNodeTreeInterfaceItem *item) { if (item && detail::item_is_type(*item)) { return reinterpret_cast(item); } return nullptr; } namespace socket_types { constexpr const char *node_socket_data_float = "NodeSocketFloat"; constexpr const char *node_socket_data_int = "NodeSocketInt"; constexpr const char *node_socket_data_bool = "NodeSocketBool"; constexpr const char *node_socket_data_rotation = "NodeSocketRotation"; constexpr const char *node_socket_data_vector = "NodeSocketVector"; constexpr const char *node_socket_data_color = "NodeSocketColor"; constexpr const char *node_socket_data_string = "NodeSocketString"; constexpr const char *node_socket_data_object = "NodeSocketObject"; constexpr const char *node_socket_data_image = "NodeSocketImage"; constexpr const char *node_socket_data_collection = "NodeSocketCollection"; constexpr const char *node_socket_data_texture = "NodeSocketTexture"; constexpr const char *node_socket_data_material = "NodeSocketMaterial"; template void socket_data_to_static_type(const char *socket_type, const Fn &fn) { if (STREQ(socket_type, socket_types::node_socket_data_float)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_int)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_bool)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_rotation)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_vector)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_color)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_string)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_object)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_image)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_collection)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_texture)) { fn.template operator()(); } else if (STREQ(socket_type, socket_types::node_socket_data_material)) { fn.template operator()(); } } namespace detail { template struct TypeTagExecutor { const Fn &fn; TypeTagExecutor(const Fn &fn_) : fn(fn_) {} template void operator()() const { fn(TypeTag{}); } }; } // namespace detail template void socket_data_to_static_type_tag(const char *socket_type, const Fn &fn) { detail::TypeTagExecutor executor{fn}; socket_data_to_static_type(socket_type, executor); } } // namespace socket_types template bool socket_data_is_type(const char *socket_type) { bool match = false; socket_types::socket_data_to_static_type_tag(socket_type, [&match](auto type_tag) { using SocketDataType = typename decltype(type_tag)::type; match |= std::is_same_v; }); return match; } template T &get_socket_data_as(bNodeTreeInterfaceSocket &item) { BLI_assert(socket_data_is_type(item.socket_type)); return *static_cast(item.socket_data); } template const T &get_socket_data_as(const bNodeTreeInterfaceSocket &item) { BLI_assert(socket_data_is_type(item.socket_type)); return *static_cast(item.socket_data); } inline bNodeTreeInterfaceSocket *add_interface_socket_from_node(bNodeTree &ntree, const bNode & /*from_node*/, const bNodeSocket &from_sock, const StringRefNull socket_type, const StringRefNull name) { eNodeTreeInterfaceSocketFlag flag = eNodeTreeInterfaceSocketFlag(0); SET_FLAG_FROM_TEST(flag, from_sock.in_out & SOCK_IN, NODE_INTERFACE_SOCKET_INPUT); SET_FLAG_FROM_TEST(flag, from_sock.in_out & SOCK_OUT, NODE_INTERFACE_SOCKET_OUTPUT); bNodeTreeInterfaceSocket *iosock = ntree.tree_interface.add_socket( name.data(), from_sock.description, socket_type, flag, nullptr); if (iosock == nullptr) { return nullptr; } const bNodeSocketType *typeinfo = iosock->socket_typeinfo(); if (typeinfo->interface_from_socket) { /* XXX Enable when bNodeSocketType callbacks have been updated. */ UNUSED_VARS(from_sock); // typeinfo->interface_from_socket(ntree.id, iosock, &from_node, &from_sock); } return iosock; } inline bNodeTreeInterfaceSocket *add_interface_socket_from_node(bNodeTree &ntree, const bNode &from_node, const bNodeSocket &from_sock, const StringRefNull socket_type) { return add_interface_socket_from_node(ntree, from_node, from_sock, socket_type, from_sock.name); } inline bNodeTreeInterfaceSocket *add_interface_socket_from_node(bNodeTree &ntree, const bNode &from_node, const bNodeSocket &from_sock) { return add_interface_socket_from_node( ntree, from_node, from_sock, from_sock.typeinfo->idname, from_sock.name); } } // namespace node_interface } // namespace blender::bke