Changeset View
Changeset View
Standalone View
Standalone View
source/blender/functions/FN_field.hh
| Show First 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | public: | ||||
| } | } | ||||
| GFieldRef(const FieldNode &node, const int node_output_index = 0) | GFieldRef(const FieldNode &node, const int node_output_index = 0) | ||||
| : GFieldBase<const FieldNode *>(&node, node_output_index) | : GFieldBase<const FieldNode *>(&node, node_output_index) | ||||
| { | { | ||||
| } | } | ||||
| }; | }; | ||||
| namespace detail { | |||||
| /* Utility class to make #is_field_v work. */ | |||||
| struct TypedFieldBase { | |||||
| }; | |||||
| } // namespace detail | |||||
| /** | /** | ||||
| * A typed version of #GField. It has the same memory layout as #GField. | * A typed version of #GField. It has the same memory layout as #GField. | ||||
| */ | */ | ||||
| template<typename T> class Field : public GField { | template<typename T> class Field : public GField, detail::TypedFieldBase { | ||||
| public: | public: | ||||
| using base_type = T; | |||||
| Field() = default; | Field() = default; | ||||
| Field(GField field) : GField(std::move(field)) | Field(GField field) : GField(std::move(field)) | ||||
| { | { | ||||
| BLI_assert(this->cpp_type().template is<T>()); | BLI_assert(this->cpp_type().template is<T>()); | ||||
| } | } | ||||
| Field(std::shared_ptr<FieldNode> node, const int node_output_index = 0) | Field(std::shared_ptr<FieldNode> node, const int node_output_index = 0) | ||||
| : Field(GField(std::move(node), node_output_index)) | : Field(GField(std::move(node), node_output_index)) | ||||
| { | { | ||||
| } | } | ||||
| }; | }; | ||||
| /** True when T is any Field<...> type. */ | |||||
| template<typename T> | |||||
| static constexpr bool is_field_v = std::is_base_of_v<detail::TypedFieldBase, T> && | |||||
| !std::is_same_v<detail::TypedFieldBase, T>; | |||||
| /** | /** | ||||
| * A #FieldNode that allows composing existing fields into new fields. | * A #FieldNode that allows composing existing fields into new fields. | ||||
| */ | */ | ||||
| class FieldOperation : public FieldNode { | class FieldOperation : public FieldNode { | ||||
| /** | /** | ||||
| * The multi-function used by this node. It is optionally owned. | * The multi-function used by this node. It is optionally owned. | ||||
| * Multi-functions with mutable or vector parameters are not supported currently. | * Multi-functions with mutable or vector parameters are not supported currently. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | |||||
| template<typename T> Field<T> make_constant_field(T value) | template<typename T> Field<T> make_constant_field(T value) | ||||
| { | { | ||||
| auto constant_fn = std::make_unique<fn::CustomMF_Constant<T>>(std::forward<T>(value)); | auto constant_fn = std::make_unique<fn::CustomMF_Constant<T>>(std::forward<T>(value)); | ||||
| auto operation = std::make_shared<FieldOperation>(std::move(constant_fn)); | auto operation = std::make_shared<FieldOperation>(std::move(constant_fn)); | ||||
| return Field<T>{GField{std::move(operation), 0}}; | return Field<T>{GField{std::move(operation), 0}}; | ||||
| } | } | ||||
| GField make_constant_field(const CPPType &type, const void *value); | |||||
| GField make_field_constant_if_possible(GField field); | GField make_field_constant_if_possible(GField field); | ||||
| class IndexFieldInput final : public FieldInput { | class IndexFieldInput final : public FieldInput { | ||||
| public: | public: | ||||
| IndexFieldInput(); | IndexFieldInput(); | ||||
| static GVArray get_index_varray(IndexMask mask, ResourceScope &scope); | static GVArray get_index_varray(IndexMask mask, ResourceScope &scope); | ||||
| GVArray get_varray_for_context(const FieldContext &context, | GVArray get_varray_for_context(const FieldContext &context, | ||||
| IndexMask mask, | IndexMask mask, | ||||
| ResourceScope &scope) const final; | ResourceScope &scope) const final; | ||||
| uint64_t hash() const override; | uint64_t hash() const override; | ||||
| bool is_equal_to(const fn::FieldNode &other) const override; | bool is_equal_to(const fn::FieldNode &other) const override; | ||||
| }; | }; | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Value or Field Class | |||||
| * | |||||
| * Utility class that wraps a single value and a field, to simplify accessing both of the types. | |||||
| * \{ */ | |||||
| template<typename T> struct ValueOrField { | |||||
| /** Value that is used when the field is empty. */ | |||||
| T value{}; | |||||
| Field<T> field; | |||||
| ValueOrField() = default; | |||||
| ValueOrField(T value) : value(std::move(value)) | |||||
| { | |||||
| } | |||||
| ValueOrField(Field<T> field) : field(std::move(field)) | |||||
| { | |||||
| } | |||||
| bool is_field() const | |||||
| { | |||||
| return (bool)this->field; | |||||
| } | |||||
| Field<T> as_field() const | |||||
| { | |||||
| if (this->field) { | |||||
| return this->field; | |||||
| } | |||||
| return make_constant_field(this->value); | |||||
| } | |||||
| T as_value() const | |||||
| { | |||||
| if (this->field) { | |||||
| /* This returns a default value when the field is not constant. */ | |||||
| return evaluate_constant_field(this->field); | |||||
| } | |||||
| return this->value; | |||||
| } | |||||
| }; | |||||
| /** \} */ | |||||
| /* -------------------------------------------------------------------- */ | |||||
| /** \name #FieldNode Inline Methods | /** \name #FieldNode Inline Methods | ||||
| * \{ */ | * \{ */ | ||||
| inline FieldNode::FieldNode(bool is_input, bool depends_on_input) | inline FieldNode::FieldNode(bool is_input, bool depends_on_input) | ||||
| : is_input_(is_input), depends_on_input_(depends_on_input) | : is_input_(is_input), depends_on_input_(depends_on_input) | ||||
| { | { | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 103 Lines • Show Last 20 Lines | |||||