diff options
Diffstat (limited to 'source/blender/nodes/intern/node_socket_declarations.cc')
-rw-r--r-- | source/blender/nodes/intern/node_socket_declarations.cc | 163 |
1 files changed, 139 insertions, 24 deletions
diff --git a/source/blender/nodes/intern/node_socket_declarations.cc b/source/blender/nodes/intern/node_socket_declarations.cc index 1795cc339e7..4fef5b96e9f 100644 --- a/source/blender/nodes/intern/node_socket_declarations.cc +++ b/source/blender/nodes/intern/node_socket_declarations.cc @@ -23,6 +23,52 @@ namespace blender::nodes::decl { +/** + * \note This function only deals with declarations, not the field status of existing nodes. If the + * field status of existing nodes was stored on the sockets, an improvement would be to check the + * existing socket's current status instead of the declaration. + */ +static bool field_types_are_compatible(const SocketDeclaration &input, + const SocketDeclaration &output) +{ + if (output.output_field_dependency().field_type() == OutputSocketFieldType::FieldSource) { + if (input.input_field_type() == InputSocketFieldType::None) { + return false; + } + } + return true; +} + +static bool sockets_can_connect(const SocketDeclaration &socket_decl, + const bNodeSocket &other_socket) +{ + /* Input sockets cannot connect to input sockets, outputs cannot connect to outputs. */ + if (socket_decl.in_out() == other_socket.in_out) { + return false; + } + + if (other_socket.declaration) { + if (socket_decl.in_out() == SOCK_IN) { + if (!field_types_are_compatible(socket_decl, *other_socket.declaration)) { + return false; + } + } + else { + if (!field_types_are_compatible(*other_socket.declaration, socket_decl)) { + return false; + } + } + } + + return true; +} + +static bool basic_types_can_connect(const SocketDeclaration &UNUSED(socket_decl), + const bNodeSocket &other_socket) +{ + return ELEM(other_socket.type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA); +} + static void modify_subtype_except_for_storage(bNodeSocket &socket, int new_subtype) { const char *idname = nodeStaticSocketType(socket.type, new_subtype); @@ -35,10 +81,10 @@ static void modify_subtype_except_for_storage(bNodeSocket &socket, int new_subty /** \name #Float * \{ */ -bNodeSocket &Float::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const +bNodeSocket &Float::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddStaticSocket( - &ntree, &node, in_out, SOCK_FLOAT, subtype_, identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, SOCK_FLOAT, subtype_, identifier_.c_str(), name_.c_str()); this->set_common_flags(socket); bNodeSocketValueFloat &value = *(bNodeSocketValueFloat *)socket.default_value; value.min = soft_min_value_; @@ -68,10 +114,19 @@ bool Float::matches(const bNodeSocket &socket) const return true; } +bool Float::can_connect(const bNodeSocket &socket) const +{ + if (!sockets_can_connect(*this, socket)) { + return false; + } + return basic_types_can_connect(*this, socket); +} + bNodeSocket &Float::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const { if (socket.type != SOCK_FLOAT) { - return this->build(ntree, node, (eNodeSocketInOut)socket.in_out); + BLI_assert(socket.in_out == in_out_); + return this->build(ntree, node); } if (socket.typeinfo->subtype != subtype_) { modify_subtype_except_for_storage(socket, subtype_); @@ -90,10 +145,10 @@ bNodeSocket &Float::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket & /** \name #Int * \{ */ -bNodeSocket &Int::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const +bNodeSocket &Int::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddStaticSocket( - &ntree, &node, in_out, SOCK_INT, subtype_, identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, SOCK_INT, subtype_, identifier_.c_str(), name_.c_str()); this->set_common_flags(socket); bNodeSocketValueInt &value = *(bNodeSocketValueInt *)socket.default_value; value.min = soft_min_value_; @@ -123,10 +178,19 @@ bool Int::matches(const bNodeSocket &socket) const return true; } +bool Int::can_connect(const bNodeSocket &socket) const +{ + if (!sockets_can_connect(*this, socket)) { + return false; + } + return basic_types_can_connect(*this, socket); +} + bNodeSocket &Int::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const { if (socket.type != SOCK_INT) { - return this->build(ntree, node, (eNodeSocketInOut)socket.in_out); + BLI_assert(socket.in_out == in_out_); + return this->build(ntree, node); } if (socket.typeinfo->subtype != subtype_) { modify_subtype_except_for_storage(socket, subtype_); @@ -145,10 +209,10 @@ bNodeSocket &Int::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &so /** \name #Vector * \{ */ -bNodeSocket &Vector::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const +bNodeSocket &Vector::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddStaticSocket( - &ntree, &node, in_out, SOCK_VECTOR, subtype_, identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, SOCK_VECTOR, subtype_, identifier_.c_str(), name_.c_str()); this->set_common_flags(socket); bNodeSocketValueVector &value = *(bNodeSocketValueVector *)socket.default_value; copy_v3_v3(value.value, default_value_); @@ -171,10 +235,19 @@ bool Vector::matches(const bNodeSocket &socket) const return true; } +bool Vector::can_connect(const bNodeSocket &socket) const +{ + if (!sockets_can_connect(*this, socket)) { + return false; + } + return basic_types_can_connect(*this, socket); +} + bNodeSocket &Vector::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const { if (socket.type != SOCK_VECTOR) { - return this->build(ntree, node, (eNodeSocketInOut)socket.in_out); + BLI_assert(socket.in_out == in_out_); + return this->build(ntree, node); } if (socket.typeinfo->subtype != subtype_) { modify_subtype_except_for_storage(socket, subtype_); @@ -192,10 +265,10 @@ bNodeSocket &Vector::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket /** \name #Bool * \{ */ -bNodeSocket &Bool::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const +bNodeSocket &Bool::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddStaticSocket( - &ntree, &node, in_out, SOCK_BOOLEAN, PROP_NONE, identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, SOCK_BOOLEAN, PROP_NONE, identifier_.c_str(), name_.c_str()); this->set_common_flags(socket); bNodeSocketValueBoolean &value = *(bNodeSocketValueBoolean *)socket.default_value; value.value = default_value_; @@ -213,16 +286,24 @@ bool Bool::matches(const bNodeSocket &socket) const return true; } +bool Bool::can_connect(const bNodeSocket &socket) const +{ + if (!sockets_can_connect(*this, socket)) { + return false; + } + return basic_types_can_connect(*this, socket); +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name #Color * \{ */ -bNodeSocket &Color::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const +bNodeSocket &Color::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddStaticSocket( - &ntree, &node, in_out, SOCK_RGBA, PROP_NONE, identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, SOCK_RGBA, PROP_NONE, identifier_.c_str(), name_.c_str()); this->set_common_flags(socket); bNodeSocketValueRGBA &value = *(bNodeSocketValueRGBA *)socket.default_value; copy_v4_v4(value.value, default_value_); @@ -245,16 +326,24 @@ bool Color::matches(const bNodeSocket &socket) const return true; } +bool Color::can_connect(const bNodeSocket &socket) const +{ + if (!sockets_can_connect(*this, socket)) { + return false; + } + return basic_types_can_connect(*this, socket); +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name #String * \{ */ -bNodeSocket &String::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const +bNodeSocket &String::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddStaticSocket( - &ntree, &node, in_out, SOCK_STRING, PROP_NONE, identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, SOCK_STRING, PROP_NONE, identifier_.c_str(), name_.c_str()); STRNCPY(((bNodeSocketValueString *)socket.default_value)->value, default_value_.c_str()); this->set_common_flags(socket); return socket; @@ -271,18 +360,21 @@ bool String::matches(const bNodeSocket &socket) const return true; } +bool String::can_connect(const bNodeSocket &socket) const +{ + return sockets_can_connect(*this, socket) && socket.type == SOCK_STRING; +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name #IDSocketDeclaration * \{ */ -bNodeSocket &IDSocketDeclaration::build(bNodeTree &ntree, - bNode &node, - eNodeSocketInOut in_out) const +bNodeSocket &IDSocketDeclaration::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddSocket( - &ntree, &node, in_out, idname_, identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, idname_, identifier_.c_str(), name_.c_str()); this->set_common_flags(socket); return socket; } @@ -298,12 +390,18 @@ bool IDSocketDeclaration::matches(const bNodeSocket &socket) const return true; } +bool IDSocketDeclaration::can_connect(const bNodeSocket &socket) const +{ + return sockets_can_connect(*this, socket) && STREQ(socket.idname, idname_); +} + bNodeSocket &IDSocketDeclaration::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const { if (StringRef(socket.idname) != idname_) { - return this->build(ntree, node, (eNodeSocketInOut)socket.in_out); + BLI_assert(socket.in_out == in_out_); + return this->build(ntree, node); } this->set_common_flags(socket); return socket; @@ -315,10 +413,10 @@ bNodeSocket &IDSocketDeclaration::update_or_build(bNodeTree &ntree, /** \name #Geometry * \{ */ -bNodeSocket &Geometry::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const +bNodeSocket &Geometry::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddSocket( - &ntree, &node, in_out, "NodeSocketGeometry", identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, "NodeSocketGeometry", identifier_.c_str(), name_.c_str()); this->set_common_flags(socket); return socket; } @@ -334,6 +432,11 @@ bool Geometry::matches(const bNodeSocket &socket) const return true; } +bool Geometry::can_connect(const bNodeSocket &socket) const +{ + return sockets_can_connect(*this, socket) && socket.type == SOCK_GEOMETRY; +} + Span<GeometryComponentType> Geometry::supported_types() const { return supported_types_; @@ -380,10 +483,10 @@ GeometryBuilder &GeometryBuilder::only_instances(bool value) /** \name #Shader * \{ */ -bNodeSocket &Shader::build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const +bNodeSocket &Shader::build(bNodeTree &ntree, bNode &node) const { bNodeSocket &socket = *nodeAddSocket( - &ntree, &node, in_out, "NodeSocketShader", identifier_.c_str(), name_.c_str()); + &ntree, &node, in_out_, "NodeSocketShader", identifier_.c_str(), name_.c_str()); this->set_common_flags(socket); return socket; } @@ -399,6 +502,18 @@ bool Shader::matches(const bNodeSocket &socket) const return true; } +bool Shader::can_connect(const bNodeSocket &socket) const +{ + if (!sockets_can_connect(*this, socket)) { + return false; + } + /* Basic types can convert to shaders, but not the other way around. */ + if (in_out_ == SOCK_IN) { + return ELEM(socket.type, SOCK_VECTOR, SOCK_RGBA, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN); + } + return socket.type == SOCK_SHADER; +} + /** \} */ } // namespace blender::nodes::decl |