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:
Diffstat (limited to 'source/blender/functions')
-rw-r--r--source/blender/functions/CMakeLists.txt3
-rw-r--r--source/blender/functions/FN_field_cpp_type.hh114
-rw-r--r--source/blender/functions/FN_field_cpp_type_make.hh51
-rw-r--r--source/blender/functions/FN_init.h13
-rw-r--r--source/blender/functions/intern/cpp_types.cc42
-rw-r--r--source/blender/functions/intern/field_cpp_type.cc39
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