Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/NOD_node_declaration.hh
| Show All 21 Lines | |||||
| #include "BLI_vector.hh" | #include "BLI_vector.hh" | ||||
| #include "DNA_node_types.h" | #include "DNA_node_types.h" | ||||
| namespace blender::nodes { | namespace blender::nodes { | ||||
| class NodeDeclarationBuilder; | class NodeDeclarationBuilder; | ||||
| enum class InputSocketFieldType { | |||||
| /** The input is required to be a single value. */ | |||||
| None, | |||||
| /** The input can be a field. */ | |||||
| IsSupported, | |||||
| /** The input can be a field and is a field implicitly if nothing is connected. */ | |||||
| Implicit, | |||||
| }; | |||||
| enum class OutputSocketFieldType { | |||||
| /** The output is always a single value. */ | |||||
| None, | |||||
| /** The output is always a field, independent of the inputs. */ | |||||
| FieldSource, | |||||
| /** If any input is a field, this output will be a field as well. */ | |||||
| DependentField, | |||||
| /** If any of a subset of inputs is a field, this out will be a field as well. */ | |||||
| PartiallyDependent, | |||||
| }; | |||||
| /** | |||||
| * Contains information about how a node output's field state depends on inputs of the same node. | |||||
| */ | |||||
| class OutputFieldDependency { | |||||
| private: | |||||
| OutputSocketFieldType type_ = OutputSocketFieldType::None; | |||||
| Vector<int> linked_input_indices_; | |||||
| public: | |||||
| static OutputFieldDependency ForFieldSource() | |||||
| { | |||||
| OutputFieldDependency field_dependency; | |||||
| field_dependency.type_ = OutputSocketFieldType::FieldSource; | |||||
| return field_dependency; | |||||
| } | |||||
| static OutputFieldDependency ForDataSource() | |||||
| { | |||||
| OutputFieldDependency field_dependency; | |||||
| field_dependency.type_ = OutputSocketFieldType::None; | |||||
| return field_dependency; | |||||
| } | |||||
| static OutputFieldDependency ForPartiallyDependentField(Vector<int> indices) | |||||
| { | |||||
| OutputFieldDependency field_dependency; | |||||
| if (indices.is_empty()) { | |||||
| field_dependency.type_ = OutputSocketFieldType::None; | |||||
| } | |||||
| else { | |||||
| field_dependency.type_ = OutputSocketFieldType::PartiallyDependent; | |||||
| field_dependency.linked_input_indices_ = std::move(indices); | |||||
| } | |||||
| return field_dependency; | |||||
| } | |||||
| static OutputFieldDependency ForDependentField() | |||||
| { | |||||
| OutputFieldDependency field_dependency; | |||||
| field_dependency.type_ = OutputSocketFieldType::DependentField; | |||||
| return field_dependency; | |||||
| } | |||||
| OutputSocketFieldType field_type() const | |||||
| { | |||||
| return type_; | |||||
| } | |||||
| Span<int> linked_input_indices() const | |||||
| { | |||||
| return linked_input_indices_; | |||||
| } | |||||
| friend bool operator==(const OutputFieldDependency &a, const OutputFieldDependency &b) | |||||
| { | |||||
| return a.type_ == b.type_ && a.linked_input_indices_ == b.linked_input_indices_; | |||||
| } | |||||
| friend bool operator!=(const OutputFieldDependency &a, const OutputFieldDependency &b) | |||||
| { | |||||
| return !(a == b); | |||||
| } | |||||
| }; | |||||
| /** | /** | ||||
| * Describes a single input or output socket. This is subclassed for different socket types. | * Describes a single input or output socket. This is subclassed for different socket types. | ||||
| */ | */ | ||||
| class SocketDeclaration { | class SocketDeclaration { | ||||
| protected: | protected: | ||||
| std::string name_; | std::string name_; | ||||
| std::string identifier_; | std::string identifier_; | ||||
| bool hide_label_ = false; | bool hide_label_ = false; | ||||
| bool hide_value_ = false; | bool hide_value_ = false; | ||||
| bool is_multi_input_ = false; | bool is_multi_input_ = false; | ||||
| bool no_mute_links_ = false; | bool no_mute_links_ = false; | ||||
| InputSocketFieldType input_field_type_ = InputSocketFieldType::None; | |||||
| OutputFieldDependency output_field_dependency_; | |||||
| friend NodeDeclarationBuilder; | friend NodeDeclarationBuilder; | ||||
| template<typename SocketDecl> friend class SocketDeclarationBuilder; | template<typename SocketDecl> friend class SocketDeclarationBuilder; | ||||
| public: | public: | ||||
| virtual ~SocketDeclaration() = default; | virtual ~SocketDeclaration() = default; | ||||
| virtual bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const = 0; | virtual bNodeSocket &build(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out) const = 0; | ||||
| virtual bool matches(const bNodeSocket &socket) const = 0; | virtual bool matches(const bNodeSocket &socket) const = 0; | ||||
| virtual bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const; | virtual bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const; | ||||
| StringRefNull name() const; | StringRefNull name() const; | ||||
| StringRefNull identifier() const; | StringRefNull identifier() const; | ||||
| InputSocketFieldType input_field_type() const; | |||||
| const OutputFieldDependency &output_field_dependency() const; | |||||
| protected: | protected: | ||||
| void set_common_flags(bNodeSocket &socket) const; | void set_common_flags(bNodeSocket &socket) const; | ||||
| bool matches_common_data(const bNodeSocket &socket) const; | bool matches_common_data(const bNodeSocket &socket) const; | ||||
| }; | }; | ||||
| class BaseSocketDeclarationBuilder { | class BaseSocketDeclarationBuilder { | ||||
| public: | public: | ||||
| virtual ~BaseSocketDeclarationBuilder() = default; | virtual ~BaseSocketDeclarationBuilder() = default; | ||||
| Show All 32 Lines | Self &multi_input(bool value = true) | ||||
| return *(Self *)this; | return *(Self *)this; | ||||
| } | } | ||||
| Self &no_muted_links(bool value = true) | Self &no_muted_links(bool value = true) | ||||
| { | { | ||||
| decl_->no_mute_links_ = value; | decl_->no_mute_links_ = value; | ||||
| return *(Self *)this; | return *(Self *)this; | ||||
| } | } | ||||
| /** The input socket allows passing in a field. */ | |||||
| Self &supports_field() | |||||
| { | |||||
| decl_->input_field_type_ = InputSocketFieldType::IsSupported; | |||||
| return *(Self *)this; | |||||
| } | |||||
| /** The input supports a field and is a field by default when nothing is connected. */ | |||||
| Self &implicit_field() | |||||
| { | |||||
| decl_->input_field_type_ = InputSocketFieldType::Implicit; | |||||
| return *(Self *)this; | |||||
| } | |||||
| /** The output is always a field, regardless of any inputs. */ | |||||
| Self &field_source() | |||||
| { | |||||
| decl_->output_field_dependency_ = OutputFieldDependency::ForFieldSource(); | |||||
| return *(Self *)this; | |||||
| } | |||||
| /** The output is a field if any of the inputs is a field. */ | |||||
| Self &dependent_field() | |||||
| { | |||||
| decl_->output_field_dependency_ = OutputFieldDependency::ForDependentField(); | |||||
| return *(Self *)this; | |||||
| } | |||||
| /** The output is a field if any of the inputs with indices in the given list is a field. */ | |||||
| Self &dependent_field(Vector<int> input_dependencies) | |||||
| { | |||||
| decl_->output_field_dependency_ = OutputFieldDependency::ForPartiallyDependentField( | |||||
| std::move(input_dependencies)); | |||||
| } | |||||
| }; | }; | ||||
| using SocketDeclarationPtr = std::unique_ptr<SocketDeclaration>; | using SocketDeclarationPtr = std::unique_ptr<SocketDeclaration>; | ||||
| class NodeDeclaration { | class NodeDeclaration { | ||||
| private: | private: | ||||
| Vector<SocketDeclarationPtr> inputs_; | Vector<SocketDeclarationPtr> inputs_; | ||||
| Vector<SocketDeclarationPtr> outputs_; | Vector<SocketDeclarationPtr> outputs_; | ||||
| bool is_function_node_ = false; | |||||
| friend NodeDeclarationBuilder; | friend NodeDeclarationBuilder; | ||||
| public: | public: | ||||
| void build(bNodeTree &ntree, bNode &node) const; | void build(bNodeTree &ntree, bNode &node) const; | ||||
| bool matches(const bNode &node) const; | bool matches(const bNode &node) const; | ||||
| Span<SocketDeclarationPtr> inputs() const; | Span<SocketDeclarationPtr> inputs() const; | ||||
| Span<SocketDeclarationPtr> outputs() const; | Span<SocketDeclarationPtr> outputs() const; | ||||
| bool is_function_node() const | |||||
| { | |||||
| return is_function_node_; | |||||
| } | |||||
| MEM_CXX_CLASS_ALLOC_FUNCS("NodeDeclaration") | MEM_CXX_CLASS_ALLOC_FUNCS("NodeDeclaration") | ||||
| }; | }; | ||||
| class NodeDeclarationBuilder { | class NodeDeclarationBuilder { | ||||
| private: | private: | ||||
| NodeDeclaration &declaration_; | NodeDeclaration &declaration_; | ||||
| Vector<std::unique_ptr<BaseSocketDeclarationBuilder>> builders_; | Vector<std::unique_ptr<BaseSocketDeclarationBuilder>> builders_; | ||||
| public: | public: | ||||
| NodeDeclarationBuilder(NodeDeclaration &declaration); | NodeDeclarationBuilder(NodeDeclaration &declaration); | ||||
| void is_function_node(bool value = true) | |||||
| { | |||||
| declaration_.is_function_node_ = value; | |||||
| } | |||||
| template<typename DeclType> | template<typename DeclType> | ||||
| typename DeclType::Builder &add_input(StringRef name, StringRef identifier = ""); | typename DeclType::Builder &add_input(StringRef name, StringRef identifier = ""); | ||||
| template<typename DeclType> | template<typename DeclType> | ||||
| typename DeclType::Builder &add_output(StringRef name, StringRef identifier = ""); | typename DeclType::Builder &add_output(StringRef name, StringRef identifier = ""); | ||||
| private: | private: | ||||
| template<typename DeclType> | template<typename DeclType> | ||||
| typename DeclType::Builder &add_socket(StringRef name, | typename DeclType::Builder &add_socket(StringRef name, | ||||
| Show All 10 Lines | inline StringRefNull SocketDeclaration::name() const | ||||
| return name_; | return name_; | ||||
| } | } | ||||
| inline StringRefNull SocketDeclaration::identifier() const | inline StringRefNull SocketDeclaration::identifier() const | ||||
| { | { | ||||
| return identifier_; | return identifier_; | ||||
| } | } | ||||
| inline InputSocketFieldType SocketDeclaration::input_field_type() const | |||||
| { | |||||
| return input_field_type_; | |||||
| } | |||||
| inline const OutputFieldDependency &SocketDeclaration::output_field_dependency() const | |||||
| { | |||||
| return output_field_dependency_; | |||||
| } | |||||
| /* -------------------------------------------------------------------- | /* -------------------------------------------------------------------- | ||||
| * NodeDeclarationBuilder inline methods. | * NodeDeclarationBuilder inline methods. | ||||
| */ | */ | ||||
| inline NodeDeclarationBuilder::NodeDeclarationBuilder(NodeDeclaration &declaration) | inline NodeDeclarationBuilder::NodeDeclarationBuilder(NodeDeclaration &declaration) | ||||
| : declaration_(declaration) | : declaration_(declaration) | ||||
| { | { | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 47 Lines • Show Last 20 Lines | |||||