diff options
author | Hans Goudey <h.goudey@me.com> | 2021-12-15 18:51:57 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2021-12-15 18:51:57 +0300 |
commit | 11be151d58ec0ca955f019b0eed738e3245110b8 (patch) | |
tree | 5f9673d5a91060fb3bb2156dddb32c2e95409b48 /source/blender/nodes/NOD_node_declaration.hh | |
parent | 474adc6f883c2d5a854d7324364f7996044d83cb (diff) |
Node Editor: Link Drag Search Menu
This commit adds a search menu when links are dragged above empty
space. When releasing the drag, a menu displays all compatible
sockets with the source link. The "main" sockets (usually the first)
are weighted above other sockets in the search, so they appear first
when you type the name of the node.
A few special operators for creating a reroute or a group input node
are also added to the search.
Translation is started after choosing a node so it can be placed
quickly, since users would likely adjust the position after anyway.
A small "+" is displayed next to the cursor to give a hint about this.
Further improvements are possible after this first iteration:
- Support custom node trees.
- Better drawing of items in the search menu.
- Potential tweaks to filtering of items, depending on user feedback.
Thanks to Juanfran Matheu for developing an initial patch.
Differential Revision: https://developer.blender.org/D8286
Diffstat (limited to 'source/blender/nodes/NOD_node_declaration.hh')
-rw-r--r-- | source/blender/nodes/NOD_node_declaration.hh | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh index cccaf93a7d7..af2130ec452 100644 --- a/source/blender/nodes/NOD_node_declaration.hh +++ b/source/blender/nodes/NOD_node_declaration.hh @@ -16,6 +16,7 @@ #pragma once +#include <functional> #include <type_traits> #include "BLI_string_ref.hh" @@ -23,6 +24,8 @@ #include "DNA_node_types.h" +struct bNode; + namespace blender::nodes { class NodeDeclarationBuilder; @@ -84,6 +87,9 @@ class SocketDeclaration { std::string name_; std::string identifier_; std::string description_; + /** Defined by whether the socket is part of the node's input or + * output socket declaration list. Included here for convenience. */ + eNodeSocketInOut in_out_; bool hide_label_ = false; bool hide_value_ = false; bool compact_ = false; @@ -95,19 +101,36 @@ class SocketDeclaration { InputSocketFieldType input_field_type_ = InputSocketFieldType::None; OutputFieldDependency output_field_dependency_; + /** Utility method to make the socket available if there is a straightforward way to do so. */ + std::function<void(bNode &)> make_available_fn_; + friend NodeDeclarationBuilder; template<typename SocketDecl> friend class SocketDeclarationBuilder; public: virtual ~SocketDeclaration() = default; - virtual bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const = 0; + virtual bNodeSocket &build(bNodeTree &ntree, bNode &node) const = 0; virtual bool matches(const bNodeSocket &socket) const = 0; virtual bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const; + /** + * Determine if a new socket described by this declaration could have a valid connection + * the other socket. + */ + virtual bool can_connect(const bNodeSocket &socket) const = 0; + + /** + * Change the node such that the socket will become visible. The node type's update method + * should be called afterwards. + * \note Note that this is not necessarily implemented for all node types. + */ + void make_available(bNode &node) const; + StringRefNull name() const; StringRefNull description() const; StringRefNull identifier() const; + eNodeSocketInOut in_out() const; bool is_attribute_name() const; bool is_default_link_socket() const; @@ -216,6 +239,18 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder { std::move(input_dependencies)); return *(Self *)this; } + + /** + * Pass a function that sets properties on the node required to make the corresponding socket + * available, if it is not available on the default state of the node. The function is allowed to + * make other sockets unavailable, since it is meant to be called when the node is first added. + * The node type's update function is called afterwards. + */ + Self &make_available(std::function<void(bNode &)> fn) + { + decl_->make_available_fn_ = std::move(fn); + return *(Self *)this; + } }; using SocketDeclarationPtr = std::unique_ptr<SocketDeclaration>; @@ -233,6 +268,7 @@ class NodeDeclaration { Span<SocketDeclarationPtr> inputs() const; Span<SocketDeclarationPtr> outputs() const; + Span<SocketDeclarationPtr> sockets(eNodeSocketInOut in_out) const; bool is_function_node() const { @@ -268,7 +304,7 @@ class NodeDeclarationBuilder { template<typename DeclType> typename DeclType::Builder &add_socket(StringRef name, StringRef identifier, - Vector<SocketDeclarationPtr> &r_decls); + eNodeSocketInOut in_out); }; /* -------------------------------------------------------------------- */ @@ -361,6 +397,11 @@ inline StringRefNull SocketDeclaration::identifier() const return identifier_; } +inline eNodeSocketInOut SocketDeclaration::in_out() const +{ + return in_out_; +} + inline StringRefNull SocketDeclaration::description() const { return description_; @@ -386,6 +427,13 @@ inline const OutputFieldDependency &SocketDeclaration::output_field_dependency() return output_field_dependency_; } +inline void SocketDeclaration::make_available(bNode &node) const +{ + if (make_available_fn_) { + make_available_fn_(node); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -401,28 +449,34 @@ template<typename DeclType> inline typename DeclType::Builder &NodeDeclarationBuilder::add_input(StringRef name, StringRef identifier) { - return this->add_socket<DeclType>(name, identifier, declaration_.inputs_); + return this->add_socket<DeclType>(name, identifier, SOCK_IN); } template<typename DeclType> inline typename DeclType::Builder &NodeDeclarationBuilder::add_output(StringRef name, StringRef identifier) { - return this->add_socket<DeclType>(name, identifier, declaration_.outputs_); + return this->add_socket<DeclType>(name, identifier, SOCK_OUT); } template<typename DeclType> -inline typename DeclType::Builder &NodeDeclarationBuilder::add_socket( - StringRef name, StringRef identifier, Vector<SocketDeclarationPtr> &r_decls) +inline typename DeclType::Builder &NodeDeclarationBuilder::add_socket(StringRef name, + StringRef identifier, + eNodeSocketInOut in_out) { static_assert(std::is_base_of_v<SocketDeclaration, DeclType>); using Builder = typename DeclType::Builder; + + Vector<SocketDeclarationPtr> &declarations = in_out == SOCK_IN ? declaration_.inputs_ : + declaration_.outputs_; + std::unique_ptr<DeclType> socket_decl = std::make_unique<DeclType>(); std::unique_ptr<Builder> socket_decl_builder = std::make_unique<Builder>(); socket_decl_builder->decl_ = &*socket_decl; socket_decl->name_ = name; socket_decl->identifier_ = identifier.is_empty() ? name : identifier; - r_decls.append(std::move(socket_decl)); + socket_decl->in_out_ = in_out; + declarations.append(std::move(socket_decl)); Builder &socket_decl_builder_ref = *socket_decl_builder; builders_.append(std::move(socket_decl_builder)); return socket_decl_builder_ref; @@ -444,6 +498,14 @@ inline Span<SocketDeclarationPtr> NodeDeclaration::outputs() const return outputs_; } +inline Span<SocketDeclarationPtr> NodeDeclaration::sockets(eNodeSocketInOut in_out) const +{ + if (in_out == SOCK_IN) { + return inputs_; + } + return outputs_; +} + /** \} */ } // namespace blender::nodes |