Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-09-23 23:21:31 +0300
committerHans Goudey <h.goudey@me.com>2021-09-23 23:21:31 +0300
commit61f3d4eb7c7db711f9339d05e68b8f9eac3ce167 (patch)
tree9004c577411998029bda688d5659d1a98be484f4 /source/blender/nodes/NOD_node_declaration.hh
parentc1b925f7fff5f8b26daa05b3105cbb10dfc175e7 (diff)
Geometry Nodes: Initial socket visualization for fields.
This implements the update logic for the vizualization of which sockets pass data or constants directly, and which pass functions. The socket shapes may still have to be updated. That should be done separately, because it might be a bit more involved, because socket shapes are currently linked to keyframe shapes. Currently the circle and diamond shapes are used with the following meanings: - Input Sockets: - Circle: Required to be a single value. - Diamond: This input supports fields. - Output Sockets: - Circle: This output is a single value. - Diamond: This output may be a field. Connecting a field to a circle input socket is an error, since a field cannot be converted to a single value. If the socket shape is a diamond with a dot in the middle, it means it is currently a single value, but could be a field. In addition to socket shapes, the intention is to draw node links differently based on the field status. However, the exact method for conveying that isn't decided yet. Differential Revision: https://developer.blender.org/D12584
Diffstat (limited to 'source/blender/nodes/NOD_node_declaration.hh')
-rw-r--r--source/blender/nodes/NOD_node_declaration.hh151
1 files changed, 151 insertions, 0 deletions
diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh
index 8e9e72bf4c8..32e63ffb2df 100644
--- a/source/blender/nodes/NOD_node_declaration.hh
+++ b/source/blender/nodes/NOD_node_declaration.hh
@@ -27,6 +27,91 @@ namespace blender::nodes {
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.
+ * The subset is defined by the vector of indices. */
+ 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.
*/
@@ -39,6 +124,9 @@ class SocketDeclaration {
bool is_multi_input_ = false;
bool no_mute_links_ = false;
+ InputSocketFieldType input_field_type_ = InputSocketFieldType::None;
+ OutputFieldDependency output_field_dependency_;
+
friend NodeDeclarationBuilder;
template<typename SocketDecl> friend class SocketDeclarationBuilder;
@@ -52,6 +140,9 @@ class SocketDeclaration {
StringRefNull name() const;
StringRefNull identifier() const;
+ InputSocketFieldType input_field_type() const;
+ const OutputFieldDependency &output_field_dependency() const;
+
protected:
void set_common_flags(bNodeSocket &socket) const;
bool matches_common_data(const bNodeSocket &socket) const;
@@ -100,6 +191,41 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder {
decl_->no_mute_links_ = value;
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>;
@@ -108,6 +234,7 @@ class NodeDeclaration {
private:
Vector<SocketDeclarationPtr> inputs_;
Vector<SocketDeclarationPtr> outputs_;
+ bool is_function_node_ = false;
friend NodeDeclarationBuilder;
@@ -118,6 +245,11 @@ class NodeDeclaration {
Span<SocketDeclarationPtr> inputs() const;
Span<SocketDeclarationPtr> outputs() const;
+ bool is_function_node() const
+ {
+ return is_function_node_;
+ }
+
MEM_CXX_CLASS_ALLOC_FUNCS("NodeDeclaration")
};
@@ -129,6 +261,15 @@ class NodeDeclarationBuilder {
public:
NodeDeclarationBuilder(NodeDeclaration &declaration);
+ /**
+ * All inputs support fields, and all outputs are fields if any of the inputs is a field.
+ * Calling field status definitions on each socket is unnecessary.
+ */
+ void is_function_node(bool value = true)
+ {
+ declaration_.is_function_node_ = value;
+ }
+
template<typename DeclType>
typename DeclType::Builder &add_input(StringRef name, StringRef identifier = "");
template<typename DeclType>
@@ -155,6 +296,16 @@ inline StringRefNull SocketDeclaration::identifier() const
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.
*/