diff options
Diffstat (limited to 'source/blender/functions')
-rw-r--r-- | source/blender/functions/CMakeLists.txt | 3 | ||||
-rw-r--r-- | source/blender/functions/FN_field_cpp_type.hh | 114 | ||||
-rw-r--r-- | source/blender/functions/FN_field_cpp_type_make.hh | 51 | ||||
-rw-r--r-- | source/blender/functions/FN_init.h | 13 | ||||
-rw-r--r-- | source/blender/functions/intern/cpp_types.cc | 42 | ||||
-rw-r--r-- | source/blender/functions/intern/field_cpp_type.cc | 39 |
6 files changed, 167 insertions, 95 deletions
diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt index 3d153813425..54f67122907 100644 --- a/source/blender/functions/CMakeLists.txt +++ b/source/blender/functions/CMakeLists.txt @@ -13,6 +13,7 @@ set(INC_SYS set(SRC intern/cpp_types.cc intern/field.cc + intern/field_cpp_type.cc intern/lazy_function.cc intern/lazy_function_execute.cc intern/lazy_function_graph.cc @@ -27,6 +28,8 @@ set(SRC FN_field.hh FN_field_cpp_type.hh + FN_field_cpp_type_make.hh + FN_init.h FN_lazy_function.hh FN_lazy_function_execute.hh FN_lazy_function_graph.hh diff --git a/source/blender/functions/FN_field_cpp_type.hh b/source/blender/functions/FN_field_cpp_type.hh index 6900a093dc6..cbb2a576272 100644 --- a/source/blender/functions/FN_field_cpp_type.hh +++ b/source/blender/functions/FN_field_cpp_type.hh @@ -6,49 +6,15 @@ * \ingroup fn */ -#include "BLI_cpp_type_make.hh" #include "FN_field.hh" namespace blender::fn { -template<typename T> struct FieldCPPTypeParam { -}; - -class FieldCPPType : public CPPType { - private: - const CPPType &base_type_; - - public: - template<typename T> - FieldCPPType(FieldCPPTypeParam<Field<T>> /* unused */, StringRef debug_name) - : CPPType(CPPTypeParam<Field<T>, CPPTypeFlags::None>(), debug_name), - base_type_(CPPType::get<T>()) - { - } - - const CPPType &base_type() const - { - return base_type_; - } - - /* Ensure that #GField and #Field<T> have the same layout, to enable casting between the two. */ - static_assert(sizeof(Field<int>) == sizeof(GField)); - static_assert(sizeof(Field<int>) == sizeof(Field<std::string>)); - - const GField &get_gfield(const void *field) const - { - return *(const GField *)field; - } - - void construct_from_gfield(void *r_value, const GField &gfield) const - { - new (r_value) GField(gfield); - } -}; - -class ValueOrFieldCPPType : public CPPType { +/** + * Contains information about how to deal with a `ValueOrField<T>` generically. + */ +class ValueOrFieldCPPType { private: - const CPPType &base_type_; void (*construct_from_value_)(void *dst, const void *value); void (*construct_from_field_)(void *dst, GField field); const void *(*get_value_ptr_)(const void *value_or_field); @@ -57,35 +23,12 @@ class ValueOrFieldCPPType : public CPPType { GField (*as_field_)(const void *value_or_field); public: - template<typename T> - ValueOrFieldCPPType(FieldCPPTypeParam<ValueOrField<T>> /* unused */, StringRef debug_name) - : CPPType(CPPTypeParam<ValueOrField<T>, CPPTypeFlags::Printable>(), debug_name), - base_type_(CPPType::get<T>()) - { - construct_from_value_ = [](void *dst, const void *value_or_field) { - new (dst) ValueOrField<T>(*(const T *)value_or_field); - }; - construct_from_field_ = [](void *dst, GField field) { - new (dst) ValueOrField<T>(Field<T>(std::move(field))); - }; - get_value_ptr_ = [](const void *value_or_field) { - return (const void *)&((ValueOrField<T> *)value_or_field)->value; - }; - get_field_ptr_ = [](const void *value_or_field) -> const GField * { - return &((ValueOrField<T> *)value_or_field)->field; - }; - is_field_ = [](const void *value_or_field) { - return ((ValueOrField<T> *)value_or_field)->is_field(); - }; - as_field_ = [](const void *value_or_field) -> GField { - return ((ValueOrField<T> *)value_or_field)->as_field(); - }; - } + /** The #ValueOrField<T> itself. */ + const CPPType &self; + /** The type stored in the field. */ + const CPPType &value; - const CPPType &base_type() const - { - return base_type_; - } + template<typename ValueType> ValueOrFieldCPPType(TypeTag<ValueType> /*value_type*/); void construct_from_value(void *dst, const void *value) const { @@ -122,22 +65,29 @@ class ValueOrFieldCPPType : public CPPType { { return as_field_(value_or_field); } -}; -} // namespace blender::fn + /** + * Try to find the #ValueOrFieldCPPType that corresponds to a #CPPType. + */ + static const ValueOrFieldCPPType *get_from_self(const CPPType &self); -#define MAKE_FIELD_CPP_TYPE(DEBUG_NAME, FIELD_TYPE) \ - template<> const blender::CPPType &blender::CPPType::get_impl<blender::fn::Field<FIELD_TYPE>>() \ - { \ - static blender::fn::FieldCPPType cpp_type{ \ - blender::fn::FieldCPPTypeParam<blender::fn::Field<FIELD_TYPE>>(), STRINGIFY(DEBUG_NAME)}; \ - return cpp_type; \ - } \ - template<> \ - const blender::CPPType &blender::CPPType::get_impl<blender::fn::ValueOrField<FIELD_TYPE>>() \ - { \ - static blender::fn::ValueOrFieldCPPType cpp_type{ \ - blender::fn::FieldCPPTypeParam<blender::fn::ValueOrField<FIELD_TYPE>>(), \ - STRINGIFY(DEBUG_NAME##OrValue)}; \ - return cpp_type; \ + /** + * Try to find the #ValueOrFieldCPPType that wraps a #ValueOrField containing the given value + * type. This only works when the type has been created with #FN_FIELD_CPP_TYPE_MAKE. + */ + static const ValueOrFieldCPPType *get_from_value(const CPPType &value); + + template<typename ValueType> static const ValueOrFieldCPPType &get() + { + static const ValueOrFieldCPPType &type = + ValueOrFieldCPPType::get_impl<std::decay_t<ValueType>>(); + return type; } + + private: + template<typename ValueType> static const ValueOrFieldCPPType &get_impl(); + + void register_self(); +}; + +} // namespace blender::fn diff --git a/source/blender/functions/FN_field_cpp_type_make.hh b/source/blender/functions/FN_field_cpp_type_make.hh new file mode 100644 index 00000000000..79e46faa9e7 --- /dev/null +++ b/source/blender/functions/FN_field_cpp_type_make.hh @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "FN_field_cpp_type.hh" + +namespace blender::fn { + +template<typename ValueType> +inline ValueOrFieldCPPType::ValueOrFieldCPPType(TypeTag<ValueType> /*value_type*/) + : self(CPPType::get<ValueOrField<ValueType>>()), value(CPPType::get<ValueType>()) +{ + using T = ValueType; + construct_from_value_ = [](void *dst, const void *value_or_field) { + new (dst) ValueOrField<T>(*(const T *)value_or_field); + }; + construct_from_field_ = [](void *dst, GField field) { + new (dst) ValueOrField<T>(Field<T>(std::move(field))); + }; + get_value_ptr_ = [](const void *value_or_field) { + return (const void *)&((ValueOrField<T> *)value_or_field)->value; + }; + get_field_ptr_ = [](const void *value_or_field) -> const GField * { + return &((ValueOrField<T> *)value_or_field)->field; + }; + is_field_ = [](const void *value_or_field) { + return ((ValueOrField<T> *)value_or_field)->is_field(); + }; + as_field_ = [](const void *value_or_field) -> GField { + return ((ValueOrField<T> *)value_or_field)->as_field(); + }; + this->register_self(); +} + +} // namespace blender::fn + +/** + * Create a new #ValueOrFieldCPPType that can be accessed through `ValueOrFieldCPPType::get<T>()`. + */ +#define FN_FIELD_CPP_TYPE_MAKE(VALUE_TYPE) \ + BLI_CPP_TYPE_MAKE(blender::fn::ValueOrField<VALUE_TYPE>, CPPTypeFlags::None) \ + template<> \ + const blender::fn::ValueOrFieldCPPType & \ + blender::fn::ValueOrFieldCPPType::get_impl<VALUE_TYPE>() \ + { \ + static blender::fn::ValueOrFieldCPPType type{blender::TypeTag<VALUE_TYPE>{}}; \ + return type; \ + } + +/** Register a #ValueOrFieldCPPType created with #FN_FIELD_CPP_TYPE_MAKE. */ +#define FN_FIELD_CPP_TYPE_REGISTER(VALUE_TYPE) blender::fn::ValueOrFieldCPPType::get<VALUE_TYPE>() diff --git a/source/blender/functions/FN_init.h b/source/blender/functions/FN_init.h new file mode 100644 index 00000000000..e8c9fbce57e --- /dev/null +++ b/source/blender/functions/FN_init.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void FN_register_cpp_types(void); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/functions/intern/cpp_types.cc b/source/blender/functions/intern/cpp_types.cc index f046da30994..098e7030de4 100644 --- a/source/blender/functions/intern/cpp_types.cc +++ b/source/blender/functions/intern/cpp_types.cc @@ -2,20 +2,36 @@ #include "BLI_color.hh" #include "BLI_cpp_type_make.hh" +#include "BLI_cpp_types_make.hh" #include "BLI_float4x4.hh" #include "BLI_math_vec_types.hh" -#include "FN_field_cpp_type.hh" +#include "FN_field_cpp_type_make.hh" +#include "FN_init.h" -MAKE_FIELD_CPP_TYPE(FloatField, float); -MAKE_FIELD_CPP_TYPE(Float2Field, blender::float2); -MAKE_FIELD_CPP_TYPE(Float3Field, blender::float3); -MAKE_FIELD_CPP_TYPE(ColorGeometry4fField, blender::ColorGeometry4f); -MAKE_FIELD_CPP_TYPE(ColorGeometry4bField, blender::ColorGeometry4b); -MAKE_FIELD_CPP_TYPE(BoolField, bool); -MAKE_FIELD_CPP_TYPE(Int8Field, int8_t); -MAKE_FIELD_CPP_TYPE(Int32Field, int32_t); -MAKE_FIELD_CPP_TYPE(StringField, std::string); -BLI_CPP_TYPE_MAKE(StringValueOrFieldVector, - blender::Vector<blender::fn::ValueOrField<std::string>>, - CPPTypeFlags::None); +FN_FIELD_CPP_TYPE_MAKE(float); +FN_FIELD_CPP_TYPE_MAKE(blender::float2); +FN_FIELD_CPP_TYPE_MAKE(blender::float3); +FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4f); +FN_FIELD_CPP_TYPE_MAKE(blender::ColorGeometry4b); +FN_FIELD_CPP_TYPE_MAKE(bool); +FN_FIELD_CPP_TYPE_MAKE(int8_t); +FN_FIELD_CPP_TYPE_MAKE(int32_t); +FN_FIELD_CPP_TYPE_MAKE(std::string); + +BLI_VECTOR_CPP_TYPE_MAKE(blender::fn::ValueOrField<std::string>); + +void FN_register_cpp_types() +{ + FN_FIELD_CPP_TYPE_REGISTER(float); + FN_FIELD_CPP_TYPE_REGISTER(blender::float2); + FN_FIELD_CPP_TYPE_REGISTER(blender::float3); + FN_FIELD_CPP_TYPE_REGISTER(blender::ColorGeometry4f); + FN_FIELD_CPP_TYPE_REGISTER(blender::ColorGeometry4b); + FN_FIELD_CPP_TYPE_REGISTER(bool); + FN_FIELD_CPP_TYPE_REGISTER(int8_t); + FN_FIELD_CPP_TYPE_REGISTER(int32_t); + FN_FIELD_CPP_TYPE_REGISTER(std::string); + + BLI_VECTOR_CPP_TYPE_REGISTER(blender::fn::ValueOrField<std::string>); +} diff --git a/source/blender/functions/intern/field_cpp_type.cc b/source/blender/functions/intern/field_cpp_type.cc new file mode 100644 index 00000000000..9057bbb887a --- /dev/null +++ b/source/blender/functions/intern/field_cpp_type.cc @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "FN_field_cpp_type.hh" + +namespace blender::fn { + +static auto &get_from_self_map() +{ + static Map<const CPPType *, const ValueOrFieldCPPType *> map; + return map; +} + +static auto &get_from_value_map() +{ + static Map<const CPPType *, const ValueOrFieldCPPType *> map; + return map; +} + +void ValueOrFieldCPPType::register_self() +{ + get_from_value_map().add_new(&this->value, this); + get_from_self_map().add_new(&this->self, this); +} + +const ValueOrFieldCPPType *ValueOrFieldCPPType::get_from_self(const CPPType &self) +{ + const ValueOrFieldCPPType *type = get_from_self_map().lookup_default(&self, nullptr); + BLI_assert(type == nullptr || type->self == self); + return type; +} + +const ValueOrFieldCPPType *ValueOrFieldCPPType::get_from_value(const CPPType &value) +{ + const ValueOrFieldCPPType *type = get_from_value_map().lookup_default(&value, nullptr); + BLI_assert(type == nullptr || type->value == value); + return type; +} + +} // namespace blender::fn |