Nodes: add separately allocated runtime data for nodes and sockets
This is a follow up to rBbb0fc675822f313c5546a2498a162472c2571ecb. Now the same kind of run-time data is added to nodes and sockets. Differential Revision: https://developer.blender.org/D15060
This commit is contained in:
parent
1f85877263
commit
6a59cf0530
|
@ -9,7 +9,8 @@
|
|||
|
||||
namespace blender::nodes {
|
||||
struct FieldInferencingInterface;
|
||||
}
|
||||
struct NodeDeclaration;
|
||||
} // namespace blender::nodes
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
|
@ -37,4 +38,52 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
|
|||
std::unique_ptr<nodes::FieldInferencingInterface> field_inferencing_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run-time data for every socket. This should only contain data that is somewhat persistent (i.e.
|
||||
* data that lives longer than a single depsgraph evaluation + redraw). Data that's only used in
|
||||
* smaller scopes should generally be stored in separate arrays and/or maps.
|
||||
*/
|
||||
class bNodeSocketRuntime : NonCopyable, NonMovable {
|
||||
public:
|
||||
/**
|
||||
* References a socket declaration that is owned by `node->declaration`. This is only runtime
|
||||
* data. It has to be updated when the node declaration changes.
|
||||
*/
|
||||
const SocketDeclarationHandle *declaration = nullptr;
|
||||
|
||||
/** #eNodeTreeChangedFlag. */
|
||||
uint32_t changed_flag = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Run-time data for every node. This should only contain data that is somewhat persistent (i.e.
|
||||
* data that lives longer than a single depsgraph evaluation + redraw). Data that's only used in
|
||||
* smaller scopes should generally be stored in separate arrays and/or maps.
|
||||
*/
|
||||
class bNodeRuntime : NonCopyable, NonMovable {
|
||||
public:
|
||||
/**
|
||||
* Describes the desired interface of the node. This is run-time data only.
|
||||
* The actual interface of the node may deviate from the declaration temporarily.
|
||||
* It's possible to sync the actual state of the node to the desired state. Currently, this is
|
||||
* only done when a node is created or loaded.
|
||||
*
|
||||
* In the future, we may want to keep more data only in the declaration, so that it does not have
|
||||
* to be synced to other places that are stored in files. That especially applies to data that
|
||||
* can't be edited by users directly (e.g. min/max values of sockets, tooltips, ...).
|
||||
*
|
||||
* The declaration of a node can be recreated at any time when it is used. Caching it here is
|
||||
* just a bit more efficient when it is used a lot. To make sure that the cache is up-to-date,
|
||||
* call #nodeDeclarationEnsure before using it.
|
||||
*
|
||||
* Currently, the declaration is the same for every node of the same type. Going forward, that is
|
||||
* intended to change though. Especially when nodes become more dynamic with respect to how many
|
||||
* sockets they have.
|
||||
*/
|
||||
NodeDeclarationHandle *declaration = nullptr;
|
||||
|
||||
/** #eNodeTreeChangedFlag. */
|
||||
uint32_t changed_flag = 0;
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -95,6 +95,8 @@ using blender::Stack;
|
|||
using blender::StringRef;
|
||||
using blender::Vector;
|
||||
using blender::VectorSet;
|
||||
using blender::bke::bNodeRuntime;
|
||||
using blender::bke::bNodeSocketRuntime;
|
||||
using blender::bke::bNodeTreeRuntime;
|
||||
using blender::nodes::FieldInferencingInterface;
|
||||
using blender::nodes::InputSocketFieldType;
|
||||
|
@ -662,7 +664,7 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
|
|||
BLO_read_data_address(reader, &sock->default_attribute_name);
|
||||
sock->total_inputs = 0; /* Clear runtime data set before drawing. */
|
||||
sock->cache = nullptr;
|
||||
sock->declaration = nullptr;
|
||||
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
||||
}
|
||||
|
||||
void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
||||
|
@ -682,8 +684,8 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
|
|||
|
||||
BLO_read_list(reader, &ntree->nodes);
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
node->runtime = MEM_new<bNodeRuntime>(__func__);
|
||||
node->typeinfo = nullptr;
|
||||
node->declaration = nullptr;
|
||||
|
||||
BLO_read_list(reader, &node->inputs);
|
||||
BLO_read_list(reader, &node->outputs);
|
||||
|
@ -1514,6 +1516,7 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
|
|||
unique_identifier_check, lb, "socket", '_', auto_identifier, sizeof(auto_identifier));
|
||||
|
||||
bNodeSocket *sock = MEM_cnew<bNodeSocket>("sock");
|
||||
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
||||
sock->in_out = in_out;
|
||||
|
||||
BLI_strncpy(sock->identifier, auto_identifier, NODE_MAXSTR);
|
||||
|
@ -1919,6 +1922,7 @@ static void node_socket_free(bNodeSocket *sock, const bool do_id_user)
|
|||
}
|
||||
MEM_freeN(sock->default_value);
|
||||
}
|
||||
MEM_delete(sock->runtime);
|
||||
}
|
||||
|
||||
void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
|
||||
|
@ -2124,6 +2128,7 @@ void nodeUniqueName(bNodeTree *ntree, bNode *node)
|
|||
bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idname)
|
||||
{
|
||||
bNode *node = MEM_cnew<bNode>("new node");
|
||||
node->runtime = MEM_new<bNodeRuntime>(__func__);
|
||||
BLI_addtail(&ntree->nodes, node);
|
||||
|
||||
BLI_strncpy(node->idname, idname, sizeof(node->idname));
|
||||
|
@ -2161,6 +2166,7 @@ bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type)
|
|||
|
||||
static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag)
|
||||
{
|
||||
sock_dst->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
||||
if (sock_src->prop) {
|
||||
sock_dst->prop = IDP_CopyProperty_ex(sock_src->prop, flag);
|
||||
}
|
||||
|
@ -2193,6 +2199,8 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
|
|||
bNode *node_dst = (bNode *)MEM_mallocN(sizeof(bNode), __func__);
|
||||
*node_dst = node_src;
|
||||
|
||||
node_dst->runtime = MEM_new<bNodeRuntime>(__func__);
|
||||
|
||||
/* Can be called for nodes outside a node tree (e.g. clipboard). */
|
||||
if (dst_tree) {
|
||||
if (unique_name) {
|
||||
|
@ -2253,7 +2261,6 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
|
|||
}
|
||||
|
||||
/* Reset the declaration of the new node. */
|
||||
node_dst->declaration = nullptr;
|
||||
nodeDeclarationEnsure(dst_tree, node_dst);
|
||||
|
||||
return node_dst;
|
||||
|
@ -2972,9 +2979,10 @@ static void node_free_node(bNodeTree *ntree, bNode *node)
|
|||
}
|
||||
|
||||
if (node->typeinfo->declaration_is_dynamic) {
|
||||
delete node->declaration;
|
||||
delete node->runtime->declaration;
|
||||
}
|
||||
|
||||
MEM_delete(node->runtime);
|
||||
MEM_freeN(node);
|
||||
|
||||
if (ntree) {
|
||||
|
@ -3066,6 +3074,7 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
|
|||
}
|
||||
MEM_freeN(sock->default_value);
|
||||
}
|
||||
MEM_delete(sock->runtime);
|
||||
}
|
||||
|
||||
static void free_localized_node_groups(bNodeTree *ntree)
|
||||
|
@ -3292,6 +3301,7 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree,
|
|||
}
|
||||
|
||||
bNodeSocket *sock = MEM_cnew<bNodeSocket>("socket template");
|
||||
sock->runtime = MEM_new<bNodeSocketRuntime>(__func__);
|
||||
BLI_strncpy(sock->idname, stype->idname, sizeof(sock->idname));
|
||||
sock->in_out = in_out;
|
||||
sock->type = SOCK_CUSTOM; /* int type undefined by default */
|
||||
|
@ -3679,34 +3689,34 @@ static void update_socket_declarations(ListBase *sockets,
|
|||
int index;
|
||||
LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, sockets, index) {
|
||||
const SocketDeclaration &socket_decl = *declarations[index];
|
||||
socket->declaration = &socket_decl;
|
||||
socket->runtime->declaration = &socket_decl;
|
||||
}
|
||||
}
|
||||
|
||||
void nodeSocketDeclarationsUpdate(bNode *node)
|
||||
{
|
||||
BLI_assert(node->declaration != nullptr);
|
||||
update_socket_declarations(&node->inputs, node->declaration->inputs());
|
||||
update_socket_declarations(&node->outputs, node->declaration->outputs());
|
||||
BLI_assert(node->runtime->declaration != nullptr);
|
||||
update_socket_declarations(&node->inputs, node->runtime->declaration->inputs());
|
||||
update_socket_declarations(&node->outputs, node->runtime->declaration->outputs());
|
||||
}
|
||||
|
||||
bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
if (node->declaration != nullptr) {
|
||||
if (node->runtime->declaration != nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (node->typeinfo->declare == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (node->typeinfo->declaration_is_dynamic) {
|
||||
node->declaration = new blender::nodes::NodeDeclaration();
|
||||
blender::nodes::NodeDeclarationBuilder builder{*node->declaration};
|
||||
node->runtime->declaration = new blender::nodes::NodeDeclaration();
|
||||
blender::nodes::NodeDeclarationBuilder builder{*node->runtime->declaration};
|
||||
node->typeinfo->declare(builder);
|
||||
}
|
||||
else {
|
||||
/* Declaration should have been created in #nodeRegisterType. */
|
||||
BLI_assert(node->typeinfo->fixed_declaration != nullptr);
|
||||
node->declaration = node->typeinfo->fixed_declaration;
|
||||
node->runtime->declaration = node->typeinfo->fixed_declaration;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -55,13 +55,13 @@ static void add_tree_tag(bNodeTree *ntree, const eNodeTreeChangedFlag flag)
|
|||
static void add_node_tag(bNodeTree *ntree, bNode *node, const eNodeTreeChangedFlag flag)
|
||||
{
|
||||
add_tree_tag(ntree, flag);
|
||||
node->changed_flag |= flag;
|
||||
node->runtime->changed_flag |= flag;
|
||||
}
|
||||
|
||||
static void add_socket_tag(bNodeTree *ntree, bNodeSocket *socket, const eNodeTreeChangedFlag flag)
|
||||
{
|
||||
add_tree_tag(ntree, flag);
|
||||
socket->changed_flag |= flag;
|
||||
socket->runtime->changed_flag |= flag;
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
@ -1082,7 +1082,7 @@ class NodeTreeMainUpdater {
|
|||
if (ntree.runtime->changed_flag & NTREE_CHANGED_ANY) {
|
||||
return true;
|
||||
}
|
||||
if (bnode.changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
|
||||
if (bnode.runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
|
||||
return true;
|
||||
}
|
||||
if (ntree.runtime->changed_flag & NTREE_CHANGED_LINK) {
|
||||
|
@ -1542,12 +1542,12 @@ class NodeTreeMainUpdater {
|
|||
const NodeRef &node = in_out_socket.node();
|
||||
const bNode &bnode = *node.bnode();
|
||||
const bNodeSocket &bsocket = *in_out_socket.bsocket();
|
||||
if (bsocket.changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
if (bsocket.runtime->changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
return true;
|
||||
}
|
||||
if (bnode.changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
if (bnode.runtime->changed_flag != NTREE_CHANGED_NOTHING) {
|
||||
const bool only_unused_internal_link_changed = (bnode.flag & NODE_MUTED) == 0 &&
|
||||
bnode.changed_flag ==
|
||||
bnode.runtime->changed_flag ==
|
||||
NTREE_CHANGED_INTERNAL_LINK;
|
||||
if (!only_unused_internal_link_changed) {
|
||||
return true;
|
||||
|
@ -1595,13 +1595,13 @@ class NodeTreeMainUpdater {
|
|||
{
|
||||
ntree.runtime->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
|
||||
node->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
node->runtime->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
node->update = 0;
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
|
||||
socket->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
socket->runtime->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
}
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
|
||||
socket->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
socket->runtime->changed_flag = NTREE_CHANGED_NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "BKE_image.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_node_tree_update.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_tracking.h"
|
||||
|
@ -1271,14 +1272,14 @@ static void node_file_output_socket_draw(bContext *C,
|
|||
|
||||
static bool socket_needs_attribute_search(bNode &node, bNodeSocket &socket)
|
||||
{
|
||||
if (node.declaration == nullptr) {
|
||||
if (node.runtime->declaration == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (socket.in_out == SOCK_OUT) {
|
||||
return false;
|
||||
}
|
||||
const int socket_index = BLI_findindex(&node.inputs, &socket);
|
||||
return node.declaration->inputs()[socket_index]->is_attribute_name();
|
||||
return node.runtime->declaration->inputs()[socket_index]->is_attribute_name();
|
||||
}
|
||||
|
||||
static void std_node_socket_draw(
|
||||
|
|
|
@ -982,8 +982,8 @@ static bool node_socket_has_tooltip(bNodeTree *ntree, bNodeSocket *socket)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (socket->declaration != nullptr) {
|
||||
const blender::nodes::SocketDeclaration &socket_decl = *socket->declaration;
|
||||
if (socket->runtime->declaration != nullptr) {
|
||||
const blender::nodes::SocketDeclaration &socket_decl = *socket->runtime->declaration;
|
||||
return !socket_decl.description().is_empty();
|
||||
}
|
||||
|
||||
|
@ -996,8 +996,8 @@ static char *node_socket_get_tooltip(bContext *C,
|
|||
bNodeSocket *socket)
|
||||
{
|
||||
std::stringstream output;
|
||||
if (socket->declaration != nullptr) {
|
||||
const blender::nodes::SocketDeclaration &socket_decl = *socket->declaration;
|
||||
if (socket->runtime->declaration != nullptr) {
|
||||
const blender::nodes::SocketDeclaration &socket_decl = *socket->runtime->declaration;
|
||||
blender::StringRef description = socket_decl.description();
|
||||
if (!description.is_empty()) {
|
||||
output << TIP_(description.data());
|
||||
|
|
|
@ -2048,7 +2048,7 @@ static bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketIn
|
|||
|
||||
/* Try to get the main socket based on the socket declaration. */
|
||||
nodeDeclarationEnsure(&ntree, &node);
|
||||
const nodes::NodeDeclaration *node_decl = node.declaration;
|
||||
const nodes::NodeDeclaration *node_decl = node.runtime->declaration;
|
||||
if (node_decl != nullptr) {
|
||||
Span<nodes::SocketDeclarationPtr> socket_decls = (in_out == SOCK_IN) ? node_decl->inputs() :
|
||||
node_decl->outputs();
|
||||
|
|
|
@ -73,14 +73,20 @@ class SocketDeclaration;
|
|||
} // namespace blender::nodes
|
||||
namespace blender::bke {
|
||||
class bNodeTreeRuntime;
|
||||
}
|
||||
class bNodeRuntime;
|
||||
class bNodeSocketRuntime;
|
||||
} // namespace blender::bke
|
||||
using NodeDeclarationHandle = blender::nodes::NodeDeclaration;
|
||||
using SocketDeclarationHandle = blender::nodes::SocketDeclaration;
|
||||
using bNodeTreeRuntimeHandle = blender::bke::bNodeTreeRuntime;
|
||||
using bNodeRuntimeHandle = blender::bke::bNodeRuntime;
|
||||
using bNodeSocketRuntimeHandle = blender::bke::bNodeSocketRuntime;
|
||||
#else
|
||||
typedef struct NodeDeclarationHandle NodeDeclarationHandle;
|
||||
typedef struct SocketDeclarationHandle SocketDeclarationHandle;
|
||||
typedef struct bNodeTreeRuntimeHandle bNodeTreeRuntimeHandle;
|
||||
typedef struct bNodeRuntimeHandle bNodeRuntimeHandle;
|
||||
typedef struct bNodeSocketRuntimeHandle bNodeSocketRuntimeHandle;
|
||||
#endif
|
||||
|
||||
typedef struct bNodeSocket {
|
||||
|
@ -174,15 +180,7 @@ typedef struct bNodeSocket {
|
|||
/** Custom data for inputs, only UI writes in this. */
|
||||
bNodeStack ns DNA_DEPRECATED;
|
||||
|
||||
/**
|
||||
* References a socket declaration that is owned by `node->declaration`. This is only runtime
|
||||
* data. It has to be updated when the node declaration changes.
|
||||
*/
|
||||
const SocketDeclarationHandle *declaration;
|
||||
|
||||
/** #eNodeTreeChangedFlag. */
|
||||
uint32_t changed_flag;
|
||||
char _pad[4];
|
||||
bNodeSocketRuntimeHandle *runtime;
|
||||
} bNodeSocket;
|
||||
|
||||
/** #bNodeSocket.type & #bNodeSocketType.type */
|
||||
|
@ -271,9 +269,7 @@ typedef struct bNode {
|
|||
|
||||
/** Used as a boolean for execution. */
|
||||
uint8_t need_exec;
|
||||
char _pad2[5];
|
||||
/** #eNodeTreeChangedFlag. */
|
||||
uint32_t changed_flag;
|
||||
char _pad2[1];
|
||||
|
||||
/** Custom user-defined color. */
|
||||
float color[3];
|
||||
|
@ -336,25 +332,7 @@ typedef struct bNode {
|
|||
/** Used at runtime when iterating over node branches. */
|
||||
char iter_flag;
|
||||
|
||||
/**
|
||||
* Describes the desired interface of the node. This is run-time data only.
|
||||
* The actual interface of the node may deviate from the declaration temporarily.
|
||||
* It's possible to sync the actual state of the node to the desired state. Currently, this is
|
||||
* only done when a node is created or loaded.
|
||||
*
|
||||
* In the future, we may want to keep more data only in the declaration, so that it does not have
|
||||
* to be synced to other places that are stored in files. That especially applies to data that
|
||||
* can't be edited by users directly (e.g. min/max values of sockets, tooltips, ...).
|
||||
*
|
||||
* The declaration of a node can be recreated at any time when it is used. Caching it here is
|
||||
* just a bit more efficient when it is used a lot. To make sure that the cache is up-to-date,
|
||||
* call #nodeDeclarationEnsure before using it.
|
||||
*
|
||||
* Currently, the declaration is the same for every node of the same type. Going forward, that is
|
||||
* intended to change though. Especially when nodes become more dynamic with respect to how many
|
||||
* sockets they have.
|
||||
*/
|
||||
NodeDeclarationHandle *declaration;
|
||||
bNodeRuntimeHandle *runtime;
|
||||
} bNode;
|
||||
|
||||
/* node->flag */
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "BLI_vector.hh"
|
||||
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
|
@ -597,7 +598,7 @@ inline bNodeType *NodeRef::typeinfo() const
|
|||
inline const NodeDeclaration *NodeRef::declaration() const
|
||||
{
|
||||
nodeDeclarationEnsure(this->tree().btree(), bnode_);
|
||||
return bnode_->declaration;
|
||||
return bnode_->runtime->declaration;
|
||||
}
|
||||
|
||||
inline int NodeRef::id() const
|
||||
|
|
|
@ -37,7 +37,7 @@ void GeoNodeExecParams::check_input_geometry_set(StringRef identifier,
|
|||
const GeometrySet &geometry_set) const
|
||||
{
|
||||
const SocketDeclaration &decl =
|
||||
*provider_->dnode->input_by_identifier(identifier).bsocket()->declaration;
|
||||
*provider_->dnode->input_by_identifier(identifier).bsocket()->runtime->declaration;
|
||||
const decl::Geometry *geo_decl = dynamic_cast<const decl::Geometry *>(&decl);
|
||||
if (geo_decl == nullptr) {
|
||||
return;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "DNA_collection_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
|
@ -261,8 +262,8 @@ void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user)
|
|||
}
|
||||
if (ntype->declare != nullptr) {
|
||||
nodeDeclarationEnsureOnOutdatedNode(ntree, node);
|
||||
if (!node->declaration->matches(*node)) {
|
||||
refresh_node(*ntree, *node, *node->declaration, do_id_user);
|
||||
if (!node->runtime->declaration->matches(*node)) {
|
||||
refresh_node(*ntree, *node, *node->runtime->declaration, do_id_user);
|
||||
}
|
||||
nodeSocketDeclarationsUpdate(node);
|
||||
return;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "NOD_socket_declarations_geometry.hh"
|
||||
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
|
@ -33,14 +34,14 @@ static bool sockets_can_connect(const SocketDeclaration &socket_decl,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (other_socket.declaration) {
|
||||
if (other_socket.runtime->declaration) {
|
||||
if (socket_decl.in_out() == SOCK_IN) {
|
||||
if (!field_types_are_compatible(socket_decl, *other_socket.declaration)) {
|
||||
if (!field_types_are_compatible(socket_decl, *other_socket.runtime->declaration)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!field_types_are_compatible(*other_socket.declaration, socket_decl)) {
|
||||
if (!field_types_are_compatible(*other_socket.runtime->declaration, socket_decl)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue