Files
test/source/blender/blenkernel/BKE_node_tree_interface.hh
Campbell Barton e955c94ed3 License Headers: Set copyright to "Blender Authors", add AUTHORS
Listing the "Blender Foundation" as copyright holder implied the Blender
Foundation holds copyright to files which may include work from many
developers.

While keeping copyright on headers makes sense for isolated libraries,
Blender's own code may be refactored or moved between files in a way
that makes the per file copyright holders less meaningful.

Copyright references to the "Blender Foundation" have been replaced with
"Blender Authors", with the exception of `./extern/` since these this
contains libraries which are more isolated, any changed to license
headers there can be handled on a case-by-case basis.

Some directories in `./intern/` have also been excluded:

- `./intern/cycles/` it's own `AUTHORS` file is planned.
- `./intern/opensubdiv/`.

An "AUTHORS" file has been added, using the chromium projects authors
file as a template.

Design task: #110784

Ref !110783.
2023-08-16 00:20:26 +10:00

222 lines
7.4 KiB
C++

/* 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 <queue>
#include <type_traits>
#include "BLI_parameter_pack_utils.hh"
#include "BLI_vector.hh"
namespace blender::bke {
/* Runtime topology cache for linear access to items. */
struct bNodeTreeInterfaceCache {
Vector<bNodeTreeInterfaceItem *> items;
Vector<bNodeTreeInterfaceSocket *> inputs;
Vector<bNodeTreeInterfaceSocket *> outputs;
void rebuild(bNodeTreeInterface &tree_interface);
};
namespace node_interface {
namespace detail {
template<typename T> static bool item_is_type(const bNodeTreeInterfaceItem &item)
{
bool match = false;
switch (item.item_type) {
case NODE_INTERFACE_SOCKET: {
match |= std::is_same<T, bNodeTreeInterfaceSocket>::value;
break;
}
case NODE_INTERFACE_PANEL: {
match |= std::is_same<T, bNodeTreeInterfacePanel>::value;
break;
}
}
return match;
}
} // namespace detail
template<typename T> T &get_item_as(bNodeTreeInterfaceItem &item)
{
BLI_assert(detail::item_is_type<T>(item));
return reinterpret_cast<T &>(item);
}
template<typename T> const T &get_item_as(const bNodeTreeInterfaceItem &item)
{
BLI_assert(detail::item_is_type<T>(item));
return reinterpret_cast<const T &>(item);
}
template<typename T> T *get_item_as(bNodeTreeInterfaceItem *item)
{
if (item && detail::item_is_type<T>(*item)) {
return reinterpret_cast<T *>(item);
}
return nullptr;
}
template<typename T> const T *get_item_as(const bNodeTreeInterfaceItem *item)
{
if (item && detail::item_is_type<T>(*item)) {
return reinterpret_cast<const T *>(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<typename Fn> 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()<bNodeSocketValueFloat>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_int)) {
fn.template operator()<bNodeSocketValueInt>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_bool)) {
fn.template operator()<bNodeSocketValueBoolean>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_rotation)) {
fn.template operator()<bNodeSocketValueRotation>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_vector)) {
fn.template operator()<bNodeSocketValueVector>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_color)) {
fn.template operator()<bNodeSocketValueRGBA>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_string)) {
fn.template operator()<bNodeSocketValueString>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_object)) {
fn.template operator()<bNodeSocketValueObject>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_image)) {
fn.template operator()<bNodeSocketValueImage>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_collection)) {
fn.template operator()<bNodeSocketValueCollection>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_texture)) {
fn.template operator()<bNodeSocketValueTexture>();
}
else if (STREQ(socket_type, socket_types::node_socket_data_material)) {
fn.template operator()<bNodeSocketValueMaterial>();
}
}
namespace detail {
template<typename Fn> struct TypeTagExecutor {
const Fn &fn;
TypeTagExecutor(const Fn &fn_) : fn(fn_) {}
template<typename T> void operator()() const
{
fn(TypeTag<T>{});
}
};
} // namespace detail
template<typename Fn> 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<typename T> 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<T, SocketDataType>;
});
return match;
}
template<typename T> T &get_socket_data_as(bNodeTreeInterfaceSocket &item)
{
BLI_assert(socket_data_is_type<T>(item.socket_type));
return *static_cast<T *>(item.socket_data);
}
template<typename T> const T &get_socket_data_as(const bNodeTreeInterfaceSocket &item)
{
BLI_assert(socket_data_is_type<T>(item.socket_type));
return *static_cast<const T *>(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