Geometry Nodes: rename ValueOrField to SocketValueVariant
Doing this in preparation for also supporting volume grids in the same type (#115270). At some point we could also actually use an `std::variant` in this type, but that would change behavior without futher changes.
This commit is contained in:
@@ -18,18 +18,18 @@ namespace blender::bke {
|
||||
* Utility class that wraps a single value and a field, to simplify accessing both of the types.
|
||||
* \{ */
|
||||
|
||||
template<typename T> struct ValueOrField {
|
||||
template<typename T> struct SocketValueVariant {
|
||||
using Field = fn::Field<T>;
|
||||
|
||||
/** Value that is used when the field is empty. */
|
||||
T value{};
|
||||
Field field;
|
||||
|
||||
ValueOrField() = default;
|
||||
SocketValueVariant() = default;
|
||||
|
||||
ValueOrField(T value) : value(std::move(value)) {}
|
||||
SocketValueVariant(T value) : value(std::move(value)) {}
|
||||
|
||||
ValueOrField(Field field) : field(std::move(field)) {}
|
||||
SocketValueVariant(Field field) : field(std::move(field)) {}
|
||||
|
||||
bool is_field() const
|
||||
{
|
||||
@@ -53,13 +53,13 @@ template<typename T> struct ValueOrField {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const ValueOrField<T> &value_or_field)
|
||||
friend std::ostream &operator<<(std::ostream &stream, const SocketValueVariant<T> &value_variant)
|
||||
{
|
||||
if (value_or_field.field) {
|
||||
stream << "ValueOrField<T>";
|
||||
if (value_variant.field) {
|
||||
stream << "SocketValueVariant<T>";
|
||||
}
|
||||
else {
|
||||
stream << value_or_field.value;
|
||||
stream << value_variant.value;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
@@ -17,24 +17,24 @@ namespace blender::bke {
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Socket Value CPP Type Class
|
||||
*
|
||||
* Contains information about how to deal with a `ValueOrField<T>` generically.
|
||||
* Contains information about how to deal with a `SocketValueVariant<T>` generically.
|
||||
* \{ */
|
||||
|
||||
class ValueOrFieldCPPType {
|
||||
class SocketValueVariantCPPType {
|
||||
private:
|
||||
void (*construct_from_value_)(void *dst, const void *value);
|
||||
void (*construct_from_field_)(void *dst, fn::GField field);
|
||||
const fn::GField *(*get_field_ptr_)(const void *value_or_field);
|
||||
bool (*is_field_)(const void *value_or_field);
|
||||
fn::GField (*as_field_)(const void *value_or_field);
|
||||
const fn::GField *(*get_field_ptr_)(const void *value_variant);
|
||||
bool (*is_field_)(const void *value_variant);
|
||||
fn::GField (*as_field_)(const void *value_variant);
|
||||
|
||||
public:
|
||||
/** The #ValueOrField<T> itself. */
|
||||
/** The #SocketValueVariant<T> itself. */
|
||||
const CPPType &self;
|
||||
/** The type stored in the field. */
|
||||
const CPPType &value;
|
||||
|
||||
template<typename ValueType> ValueOrFieldCPPType(TypeTag<ValueType> /*value_type*/);
|
||||
template<typename ValueType> SocketValueVariantCPPType(TypeTag<ValueType> /*value_type*/);
|
||||
|
||||
void construct_from_value(void *dst, const void *value) const
|
||||
{
|
||||
@@ -46,76 +46,76 @@ class ValueOrFieldCPPType {
|
||||
construct_from_field_(dst, field);
|
||||
}
|
||||
|
||||
const void *get_value_ptr(const void *value_or_field) const
|
||||
const void *get_value_ptr(const void *value_variant) const
|
||||
{
|
||||
static_assert(offsetof(ValueOrField<int>, value) == 0);
|
||||
return value_or_field;
|
||||
static_assert(offsetof(SocketValueVariant<int>, value) == 0);
|
||||
return value_variant;
|
||||
}
|
||||
|
||||
void *get_value_ptr(void *value_or_field) const
|
||||
void *get_value_ptr(void *value_variant) const
|
||||
{
|
||||
static_assert(offsetof(ValueOrField<int>, value) == 0);
|
||||
return value_or_field;
|
||||
static_assert(offsetof(SocketValueVariant<int>, value) == 0);
|
||||
return value_variant;
|
||||
}
|
||||
|
||||
const fn::GField *get_field_ptr(const void *value_or_field) const
|
||||
const fn::GField *get_field_ptr(const void *value_variant) const
|
||||
{
|
||||
return get_field_ptr_(value_or_field);
|
||||
return get_field_ptr_(value_variant);
|
||||
}
|
||||
|
||||
bool is_field(const void *value_or_field) const
|
||||
bool is_field(const void *value_variant) const
|
||||
{
|
||||
return is_field_(value_or_field);
|
||||
return is_field_(value_variant);
|
||||
}
|
||||
|
||||
fn::GField as_field(const void *value_or_field) const
|
||||
fn::GField as_field(const void *value_variant) const
|
||||
{
|
||||
return as_field_(value_or_field);
|
||||
return as_field_(value_variant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find the #ValueOrFieldCPPType that corresponds to a #CPPType.
|
||||
* Try to find the #SocketValueVariantCPPType that corresponds to a #CPPType.
|
||||
*/
|
||||
static const ValueOrFieldCPPType *get_from_self(const CPPType &self);
|
||||
static const SocketValueVariantCPPType *get_from_self(const CPPType &self);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Try to find the #SocketValueVariantCPPType that wraps a #SocketValueVariant 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);
|
||||
static const SocketValueVariantCPPType *get_from_value(const CPPType &value);
|
||||
|
||||
template<typename ValueType> static const ValueOrFieldCPPType &get()
|
||||
template<typename ValueType> static const SocketValueVariantCPPType &get()
|
||||
{
|
||||
static const ValueOrFieldCPPType &type =
|
||||
ValueOrFieldCPPType::get_impl<std::decay_t<ValueType>>();
|
||||
static const SocketValueVariantCPPType &type =
|
||||
SocketValueVariantCPPType::get_impl<std::decay_t<ValueType>>();
|
||||
return type;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename ValueType> static const ValueOrFieldCPPType &get_impl();
|
||||
template<typename ValueType> static const SocketValueVariantCPPType &get_impl();
|
||||
|
||||
void register_self();
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
inline ValueOrFieldCPPType::ValueOrFieldCPPType(TypeTag<ValueType> /*value_type*/)
|
||||
: self(CPPType::get<ValueOrField<ValueType>>()), value(CPPType::get<ValueType>())
|
||||
inline SocketValueVariantCPPType::SocketValueVariantCPPType(TypeTag<ValueType> /*value_type*/)
|
||||
: self(CPPType::get<SocketValueVariant<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_value_ = [](void *dst, const void *value) {
|
||||
new (dst) SocketValueVariant<T>(*(const T *)value);
|
||||
};
|
||||
construct_from_field_ = [](void *dst, fn::GField field) {
|
||||
new (dst) ValueOrField<T>(fn::Field<T>(std::move(field)));
|
||||
new (dst) SocketValueVariant<T>(fn::Field<T>(std::move(field)));
|
||||
};
|
||||
get_field_ptr_ = [](const void *value_or_field) -> const fn::GField * {
|
||||
return &((ValueOrField<T> *)value_or_field)->field;
|
||||
get_field_ptr_ = [](const void *value_variant) -> const fn::GField * {
|
||||
return &((SocketValueVariant<T> *)value_variant)->field;
|
||||
};
|
||||
is_field_ = [](const void *value_or_field) {
|
||||
return ((ValueOrField<T> *)value_or_field)->is_field();
|
||||
is_field_ = [](const void *value_variant) {
|
||||
return ((SocketValueVariant<T> *)value_variant)->is_field();
|
||||
};
|
||||
as_field_ = [](const void *value_or_field) -> fn::GField {
|
||||
return ((ValueOrField<T> *)value_or_field)->as_field();
|
||||
as_field_ = [](const void *value_variant) -> fn::GField {
|
||||
return ((SocketValueVariant<T> *)value_variant)->as_field();
|
||||
};
|
||||
this->register_self();
|
||||
}
|
||||
@@ -125,18 +125,19 @@ inline ValueOrFieldCPPType::ValueOrFieldCPPType(TypeTag<ValueType> /*value_type*
|
||||
} // namespace blender::bke
|
||||
|
||||
/**
|
||||
* Create a new #ValueOrFieldCPPType that can be accessed through `ValueOrFieldCPPType::get<T>()`.
|
||||
* Create a new #SocketValueVariantCPPType that can be accessed through
|
||||
* `SocketValueVariantCPPType::get<T>()`.
|
||||
*/
|
||||
#define SOCKET_VALUE_CPP_TYPE_MAKE(VALUE_TYPE) \
|
||||
BLI_CPP_TYPE_MAKE(blender::bke::ValueOrField<VALUE_TYPE>, CPPTypeFlags::Printable) \
|
||||
BLI_CPP_TYPE_MAKE(blender::bke::SocketValueVariant<VALUE_TYPE>, CPPTypeFlags::Printable) \
|
||||
template<> \
|
||||
const blender::bke::ValueOrFieldCPPType & \
|
||||
blender::bke::ValueOrFieldCPPType::get_impl<VALUE_TYPE>() \
|
||||
const blender::bke::SocketValueVariantCPPType & \
|
||||
blender::bke::SocketValueVariantCPPType::get_impl<VALUE_TYPE>() \
|
||||
{ \
|
||||
static blender::bke::ValueOrFieldCPPType type{blender::TypeTag<VALUE_TYPE>{}}; \
|
||||
static blender::bke::SocketValueVariantCPPType type{blender::TypeTag<VALUE_TYPE>{}}; \
|
||||
return type; \
|
||||
}
|
||||
|
||||
/** Register a #ValueOrFieldCPPType created with #FN_FIELD_CPP_TYPE_MAKE. */
|
||||
/** Register a #SocketValueVariantCPPType created with #FN_FIELD_CPP_TYPE_MAKE. */
|
||||
#define SOCKET_VALUE_CPP_TYPE_REGISTER(VALUE_TYPE) \
|
||||
blender::bke::ValueOrFieldCPPType::get<VALUE_TYPE>()
|
||||
blender::bke::SocketValueVariantCPPType::get<VALUE_TYPE>()
|
||||
|
||||
@@ -48,8 +48,8 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
|
||||
break;
|
||||
}
|
||||
case SOCK_STRING: {
|
||||
const ValueOrField<std::string> &value = *static_cast<const ValueOrField<std::string> *>(
|
||||
socket_value);
|
||||
const SocketValueVariant<std::string> &value =
|
||||
*static_cast<const SocketValueVariant<std::string> *>(socket_value);
|
||||
bake_items[i] = std::make_unique<StringBakeItem>(value.as_value());
|
||||
break;
|
||||
}
|
||||
@@ -60,14 +60,15 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_RGBA: {
|
||||
const CPPType &type = get_socket_cpp_type(socket_type);
|
||||
const ValueOrFieldCPPType &value_or_field_type = *ValueOrFieldCPPType::get_from_self(type);
|
||||
const CPPType &base_type = value_or_field_type.value;
|
||||
if (!value_or_field_type.is_field(socket_value)) {
|
||||
const void *value = value_or_field_type.get_value_ptr(socket_value);
|
||||
const SocketValueVariantCPPType &value_variant_type =
|
||||
*SocketValueVariantCPPType::get_from_self(type);
|
||||
const CPPType &base_type = value_variant_type.value;
|
||||
if (!value_variant_type.is_field(socket_value)) {
|
||||
const void *value = value_variant_type.get_value_ptr(socket_value);
|
||||
bake_items[i] = std::make_unique<PrimitiveBakeItem>(base_type, value);
|
||||
break;
|
||||
}
|
||||
const fn::GField &field = *value_or_field_type.get_field_ptr(socket_value);
|
||||
const fn::GField &field = *value_variant_type.get_field_ptr(socket_value);
|
||||
if (!field.node().depends_on_input()) {
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(base_type, value);
|
||||
fn::evaluate_constant_field(field, value);
|
||||
@@ -144,11 +145,12 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
|
||||
case SOCK_BOOLEAN:
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_RGBA: {
|
||||
const ValueOrFieldCPPType &value_or_field_type = *ValueOrFieldCPPType::get_from_self(type);
|
||||
const CPPType &base_type = value_or_field_type.value;
|
||||
const SocketValueVariantCPPType &value_variant_type =
|
||||
*SocketValueVariantCPPType::get_from_self(type);
|
||||
const CPPType &base_type = value_variant_type.value;
|
||||
if (const auto *item = dynamic_cast<const PrimitiveBakeItem *>(&bake_item)) {
|
||||
if (item->type() == base_type) {
|
||||
value_or_field_type.construct_from_value(r_value, item->value());
|
||||
value_variant_type.construct_from_value(r_value, item->value());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -158,7 +160,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
|
||||
base_type);
|
||||
const AnonymousAttributeIDPtr &attribute_id = attribute_field->anonymous_id();
|
||||
fn::GField field{attribute_field};
|
||||
value_or_field_type.construct_from_field(r_value, std::move(field));
|
||||
value_variant_type.construct_from_field(r_value, std::move(field));
|
||||
r_attribute_map.add(item->name(), attribute_id);
|
||||
return true;
|
||||
}
|
||||
@@ -166,7 +168,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
|
||||
}
|
||||
case SOCK_STRING: {
|
||||
if (const auto *item = dynamic_cast<const StringBakeItem *>(&bake_item)) {
|
||||
new (r_value) ValueOrField<std::string>(item->value());
|
||||
new (r_value) SocketValueVariant<std::string>(item->value());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -70,7 +70,7 @@ SOCKET_VALUE_CPP_TYPE_MAKE(int32_t);
|
||||
SOCKET_VALUE_CPP_TYPE_MAKE(blender::int2);
|
||||
SOCKET_VALUE_CPP_TYPE_MAKE(std::string);
|
||||
|
||||
BLI_VECTOR_CPP_TYPE_MAKE(blender::bke::ValueOrField<std::string>);
|
||||
BLI_VECTOR_CPP_TYPE_MAKE(blender::bke::SocketValueVariant<std::string>);
|
||||
|
||||
void FN_register_cpp_types()
|
||||
{
|
||||
@@ -86,5 +86,5 @@ void FN_register_cpp_types()
|
||||
SOCKET_VALUE_CPP_TYPE_REGISTER(blender::int2);
|
||||
SOCKET_VALUE_CPP_TYPE_REGISTER(std::string);
|
||||
|
||||
BLI_VECTOR_CPP_TYPE_REGISTER(blender::bke::ValueOrField<std::string>);
|
||||
BLI_VECTOR_CPP_TYPE_REGISTER(blender::bke::SocketValueVariant<std::string>);
|
||||
}
|
||||
|
||||
@@ -12,32 +12,32 @@ namespace blender::bke {
|
||||
|
||||
static auto &get_from_self_map()
|
||||
{
|
||||
static Map<const CPPType *, const ValueOrFieldCPPType *> map;
|
||||
static Map<const CPPType *, const SocketValueVariantCPPType *> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
static auto &get_from_value_map()
|
||||
{
|
||||
static Map<const CPPType *, const ValueOrFieldCPPType *> map;
|
||||
static Map<const CPPType *, const SocketValueVariantCPPType *> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
void ValueOrFieldCPPType::register_self()
|
||||
void SocketValueVariantCPPType::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 SocketValueVariantCPPType *SocketValueVariantCPPType::get_from_self(const CPPType &self)
|
||||
{
|
||||
const ValueOrFieldCPPType *type = get_from_self_map().lookup_default(&self, nullptr);
|
||||
const SocketValueVariantCPPType *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 SocketValueVariantCPPType *SocketValueVariantCPPType::get_from_value(const CPPType &value)
|
||||
{
|
||||
const ValueOrFieldCPPType *type = get_from_value_map().lookup_default(&value, nullptr);
|
||||
const SocketValueVariantCPPType *type = get_from_value_map().lookup_default(&value, nullptr);
|
||||
BLI_assert(type == nullptr || type->value == value);
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ using bke::InstancesComponent;
|
||||
using bke::MeshComponent;
|
||||
using bke::MutableAttributeAccessor;
|
||||
using bke::PointCloudComponent;
|
||||
using bke::SocketValueVariant;
|
||||
using bke::SpanAttributeWriter;
|
||||
using bke::ValueOrField;
|
||||
using bke::VolumeComponent;
|
||||
using fn::Field;
|
||||
using fn::FieldContext;
|
||||
@@ -96,22 +96,22 @@ class GeoNodeExecParams {
|
||||
template<typename T> T extract_input(StringRef identifier)
|
||||
{
|
||||
if constexpr (is_field_base_type_v<T>) {
|
||||
ValueOrField<T> value_or_field = this->extract_input<ValueOrField<T>>(identifier);
|
||||
return value_or_field.as_value();
|
||||
SocketValueVariant<T> value_variant = this->extract_input<SocketValueVariant<T>>(identifier);
|
||||
return value_variant.as_value();
|
||||
}
|
||||
else if constexpr (fn::is_field_v<T>) {
|
||||
using BaseType = typename T::base_type;
|
||||
ValueOrField<BaseType> value_or_field = this->extract_input<ValueOrField<BaseType>>(
|
||||
identifier);
|
||||
return value_or_field.as_field();
|
||||
SocketValueVariant<BaseType> value_variant =
|
||||
this->extract_input<SocketValueVariant<BaseType>>(identifier);
|
||||
return value_variant.as_field();
|
||||
}
|
||||
else if constexpr (std::is_same_v<std::decay_t<T>, GField>) {
|
||||
const int index = this->get_input_index(identifier);
|
||||
const bNodeSocket &input_socket = node_.input_by_identifier(identifier);
|
||||
const CPPType &value_type = *input_socket.typeinfo->geometry_nodes_cpp_type;
|
||||
const bke::ValueOrFieldCPPType &value_or_field_type =
|
||||
*bke::ValueOrFieldCPPType::get_from_self(value_type);
|
||||
return value_or_field_type.as_field(params_.try_get_input_data_ptr(index));
|
||||
const bke::SocketValueVariantCPPType &value_variant_type =
|
||||
*bke::SocketValueVariantCPPType::get_from_self(value_type);
|
||||
return value_variant_type.as_field(params_.try_get_input_data_ptr(index));
|
||||
}
|
||||
else {
|
||||
#ifndef NDEBUG
|
||||
@@ -135,13 +135,14 @@ class GeoNodeExecParams {
|
||||
template<typename T> T get_input(StringRef identifier) const
|
||||
{
|
||||
if constexpr (is_field_base_type_v<T>) {
|
||||
ValueOrField<T> value_or_field = this->get_input<ValueOrField<T>>(identifier);
|
||||
return value_or_field.as_value();
|
||||
SocketValueVariant<T> value_variant = this->get_input<SocketValueVariant<T>>(identifier);
|
||||
return value_variant.as_value();
|
||||
}
|
||||
else if constexpr (fn::is_field_v<T>) {
|
||||
using BaseType = typename T::base_type;
|
||||
ValueOrField<BaseType> value_or_field = this->get_input<ValueOrField<BaseType>>(identifier);
|
||||
return value_or_field.as_field();
|
||||
SocketValueVariant<BaseType> value_variant = this->get_input<SocketValueVariant<BaseType>>(
|
||||
identifier);
|
||||
return value_variant.as_field();
|
||||
}
|
||||
else {
|
||||
#ifndef NDEBUG
|
||||
@@ -163,17 +164,17 @@ class GeoNodeExecParams {
|
||||
{
|
||||
using StoredT = std::decay_t<T>;
|
||||
if constexpr (is_field_base_type_v<StoredT>) {
|
||||
this->set_output(identifier, ValueOrField<StoredT>(std::forward<T>(value)));
|
||||
this->set_output(identifier, SocketValueVariant<StoredT>(std::forward<T>(value)));
|
||||
}
|
||||
else if constexpr (fn::is_field_v<StoredT>) {
|
||||
using BaseType = typename StoredT::base_type;
|
||||
this->set_output(identifier, ValueOrField<BaseType>(std::forward<T>(value)));
|
||||
this->set_output(identifier, SocketValueVariant<BaseType>(std::forward<T>(value)));
|
||||
}
|
||||
else if constexpr (std::is_same_v<std::decay_t<StoredT>, GField>) {
|
||||
bke::attribute_math::convert_to_static_type(value.cpp_type(), [&](auto dummy) {
|
||||
using ValueT = decltype(dummy);
|
||||
Field<ValueT> value_typed(std::forward<T>(value));
|
||||
this->set_output(identifier, ValueOrField<ValueT>(std::move(value_typed)));
|
||||
this->set_output(identifier, SocketValueVariant<ValueT>(std::move(value_typed)));
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -186,7 +186,7 @@ class LazyFunctionForIndexSwitchNode : public LazyFunction {
|
||||
const CPPType &cpp_type = *node.output_socket(0).typeinfo->geometry_nodes_cpp_type;
|
||||
|
||||
debug_name_ = node.name;
|
||||
inputs_.append_as("Index", CPPType::get<ValueOrField<int>>(), lf::ValueUsage::Used);
|
||||
inputs_.append_as("Index", CPPType::get<SocketValueVariant<int>>(), lf::ValueUsage::Used);
|
||||
for (const int i : storage.items_span().index_range()) {
|
||||
const bNodeSocket &input = node.input_socket(value_inputs_start + i);
|
||||
inputs_.append_as(input.identifier, cpp_type, lf::ValueUsage::Maybe);
|
||||
@@ -196,7 +196,7 @@ class LazyFunctionForIndexSwitchNode : public LazyFunction {
|
||||
|
||||
void execute_impl(lf::Params ¶ms, const lf::Context & /*context*/) const override
|
||||
{
|
||||
const ValueOrField<int> index = params.get_input<ValueOrField<int>>(0);
|
||||
const SocketValueVariant<int> index = params.get_input<SocketValueVariant<int>>(0);
|
||||
if (index.is_field() && can_be_field_) {
|
||||
Field<int> index_field = index.as_field();
|
||||
if (index_field.node().depends_on_input()) {
|
||||
@@ -256,12 +256,12 @@ class LazyFunctionForIndexSwitchNode : public LazyFunction {
|
||||
}
|
||||
|
||||
const CPPType &type = *outputs_[0].type;
|
||||
const auto &value_or_field_type = *bke::ValueOrFieldCPPType::get_from_self(type);
|
||||
const CPPType &value_type = value_or_field_type.value;
|
||||
const auto &value_variant_type = *bke::SocketValueVariantCPPType::get_from_self(type);
|
||||
const CPPType &value_type = value_variant_type.value;
|
||||
|
||||
Vector<GField> input_fields({std::move(index)});
|
||||
for (const int i : IndexRange(values_num)) {
|
||||
input_fields.append(value_or_field_type.as_field(input_values[i]));
|
||||
input_fields.append(value_variant_type.as_field(input_values[i]));
|
||||
}
|
||||
|
||||
std::unique_ptr<mf::MultiFunction> switch_fn = std::make_unique<IndexSwitchFunction>(
|
||||
@@ -269,7 +269,7 @@ class LazyFunctionForIndexSwitchNode : public LazyFunction {
|
||||
GField output_field(FieldOperation::Create(std::move(switch_fn), std::move(input_fields)));
|
||||
|
||||
void *output_ptr = params.get_output_data_ptr(0);
|
||||
value_or_field_type.construct_from_field(output_ptr, std::move(output_field));
|
||||
value_variant_type.construct_from_field(output_ptr, std::move(output_field));
|
||||
params.output_set(0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -233,21 +233,22 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
const bool use_clamp = bool(storage.clamp);
|
||||
|
||||
GField value_field = params.extract_input<GField>("Value");
|
||||
ValueOrField<int> index_value_or_field = params.extract_input<ValueOrField<int>>("Index");
|
||||
SocketValueVariant<int> index_value_variant = params.extract_input<SocketValueVariant<int>>(
|
||||
"Index");
|
||||
const CPPType &cpp_type = value_field.cpp_type();
|
||||
|
||||
if (index_value_or_field.is_field()) {
|
||||
if (index_value_variant.is_field()) {
|
||||
/* If the index is a field, the output has to be a field that still depends on the input. */
|
||||
auto fn = std::make_shared<SampleIndexFunction>(
|
||||
std::move(geometry), std::move(value_field), domain, use_clamp);
|
||||
auto op = FieldOperation::Create(std::move(fn), {index_value_or_field.as_field()});
|
||||
auto op = FieldOperation::Create(std::move(fn), {index_value_variant.as_field()});
|
||||
params.set_output("Value", GField(std::move(op)));
|
||||
}
|
||||
else if (const GeometryComponent *component = find_source_component(geometry, domain)) {
|
||||
/* Optimization for the case when the index is a single value. Here only that one index has to
|
||||
* be evaluated. */
|
||||
const int domain_size = component->attribute_domain_size(domain);
|
||||
int index = index_value_or_field.as_value();
|
||||
int index = index_value_variant.as_value();
|
||||
if (use_clamp) {
|
||||
index = std::clamp(index, 0, domain_size - 1);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
const StringRef side = node_storage(node).mode == GEO_NODE_CURVE_HANDLE_LEFT ?
|
||||
"handle_left" :
|
||||
"handle_right";
|
||||
new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>(side));
|
||||
new (r_value) SocketValueVariant<float3>(bke::AttributeFieldInput::Create<float3>(side));
|
||||
});
|
||||
b.add_input<decl::Vector>("Offset").default_value(float3(0.0f, 0.0f, 0.0f)).field_on_all();
|
||||
b.add_output<decl::Geometry>("Curve").propagate_all();
|
||||
|
||||
@@ -41,7 +41,7 @@ class LazyFunctionForSimulationInputNode final : public LazyFunction {
|
||||
|
||||
MutableSpan<int> lf_index_by_bsocket = own_lf_graph_info.mapping.lf_index_by_bsocket;
|
||||
lf_index_by_bsocket[node.output_socket(0).index_in_tree()] = outputs_.append_and_get_index_as(
|
||||
"Delta Time", CPPType::get<ValueOrField<float>>());
|
||||
"Delta Time", CPPType::get<SocketValueVariant<float>>());
|
||||
|
||||
for (const int i : simulation_items_.index_range()) {
|
||||
const NodeSimulationItem &item = simulation_items_[i];
|
||||
@@ -103,7 +103,7 @@ class LazyFunctionForSimulationInputNode final : public LazyFunction {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
if (!params.output_was_set(0)) {
|
||||
params.set_output(0, bke::ValueOrField<float>(delta_time));
|
||||
params.set_output(0, bke::SocketValueVariant<float>(delta_time));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -405,16 +405,16 @@ void mix_baked_data_item(const eNodeSocketDatatype socket_type,
|
||||
case SOCK_ROTATION:
|
||||
case SOCK_RGBA: {
|
||||
const CPPType &type = get_simulation_item_cpp_type(socket_type);
|
||||
const bke::ValueOrFieldCPPType &value_or_field_type =
|
||||
*bke::ValueOrFieldCPPType::get_from_self(type);
|
||||
if (value_or_field_type.is_field(prev) || value_or_field_type.is_field(next)) {
|
||||
const bke::SocketValueVariantCPPType &value_variant_type =
|
||||
*bke::SocketValueVariantCPPType::get_from_self(type);
|
||||
if (value_variant_type.is_field(prev) || value_variant_type.is_field(next)) {
|
||||
/* Fields are evaluated on geometries and are mixed there. */
|
||||
break;
|
||||
}
|
||||
|
||||
void *prev_value = value_or_field_type.get_value_ptr(prev);
|
||||
const void *next_value = value_or_field_type.get_value_ptr(next);
|
||||
bke::attribute_math::convert_to_static_type(value_or_field_type.value, [&](auto dummy) {
|
||||
void *prev_value = value_variant_type.get_value_ptr(prev);
|
||||
const void *next_value = value_variant_type.get_value_ptr(next);
|
||||
bke::attribute_math::convert_to_static_type(value_variant_type.value, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
*static_cast<T *>(prev_value) = bke::attribute_math::mix2(
|
||||
factor, *static_cast<T *>(prev_value), *static_cast<const T *>(next_value));
|
||||
|
||||
@@ -15,8 +15,8 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
|
||||
static void node_geo_exec(GeoNodeExecParams params)
|
||||
{
|
||||
Vector<bke::ValueOrField<std::string>> strings =
|
||||
params.extract_input<Vector<bke::ValueOrField<std::string>>>("Strings");
|
||||
Vector<bke::SocketValueVariant<std::string>> strings =
|
||||
params.extract_input<Vector<bke::SocketValueVariant<std::string>>>("Strings");
|
||||
const std::string delim = params.extract_input<std::string>("Delimiter");
|
||||
|
||||
std::string output;
|
||||
|
||||
@@ -174,7 +174,7 @@ class LazyFunctionForSwitchNode : public LazyFunction {
|
||||
const CPPType &cpp_type = *socket_type->geometry_nodes_cpp_type;
|
||||
|
||||
debug_name_ = node.name;
|
||||
inputs_.append_as("Condition", CPPType::get<ValueOrField<bool>>());
|
||||
inputs_.append_as("Condition", CPPType::get<SocketValueVariant<bool>>());
|
||||
inputs_.append_as("False", cpp_type, lf::ValueUsage::Maybe);
|
||||
inputs_.append_as("True", cpp_type, lf::ValueUsage::Maybe);
|
||||
outputs_.append_as("Value", cpp_type);
|
||||
@@ -182,7 +182,7 @@ class LazyFunctionForSwitchNode : public LazyFunction {
|
||||
|
||||
void execute_impl(lf::Params ¶ms, const lf::Context & /*context*/) const override
|
||||
{
|
||||
const ValueOrField<bool> condition = params.get_input<ValueOrField<bool>>(0);
|
||||
const SocketValueVariant<bool> condition = params.get_input<SocketValueVariant<bool>>(0);
|
||||
if (condition.is_field() && can_be_field_) {
|
||||
Field<bool> condition_field = condition.as_field();
|
||||
if (condition_field.node().depends_on_input()) {
|
||||
@@ -220,28 +220,28 @@ class LazyFunctionForSwitchNode : public LazyFunction {
|
||||
void execute_field(Field<bool> condition, lf::Params ¶ms) const
|
||||
{
|
||||
/* When the condition is a non-constant field, we need both inputs. */
|
||||
void *false_value_or_field = params.try_get_input_data_ptr_or_request(false_input_index);
|
||||
void *true_value_or_field = params.try_get_input_data_ptr_or_request(true_input_index);
|
||||
if (ELEM(nullptr, false_value_or_field, true_value_or_field)) {
|
||||
void *false_value_variant = params.try_get_input_data_ptr_or_request(false_input_index);
|
||||
void *true_value_variant = params.try_get_input_data_ptr_or_request(true_input_index);
|
||||
if (ELEM(nullptr, false_value_variant, true_value_variant)) {
|
||||
/* Try again when inputs are available. */
|
||||
return;
|
||||
}
|
||||
|
||||
const CPPType &type = *outputs_[0].type;
|
||||
const bke::ValueOrFieldCPPType &value_or_field_type = *bke::ValueOrFieldCPPType::get_from_self(
|
||||
type);
|
||||
const CPPType &value_type = value_or_field_type.value;
|
||||
const bke::SocketValueVariantCPPType &value_variant_type =
|
||||
*bke::SocketValueVariantCPPType::get_from_self(type);
|
||||
const CPPType &value_type = value_variant_type.value;
|
||||
const MultiFunction &switch_multi_function = this->get_switch_multi_function(value_type);
|
||||
|
||||
GField false_field = value_or_field_type.as_field(false_value_or_field);
|
||||
GField true_field = value_or_field_type.as_field(true_value_or_field);
|
||||
GField false_field = value_variant_type.as_field(false_value_variant);
|
||||
GField true_field = value_variant_type.as_field(true_value_variant);
|
||||
|
||||
GField output_field{FieldOperation::Create(
|
||||
switch_multi_function,
|
||||
{std::move(condition), std::move(false_field), std::move(true_field)})};
|
||||
|
||||
void *output_ptr = params.get_output_data_ptr(0);
|
||||
value_or_field_type.construct_from_field(output_ptr, std::move(output_field));
|
||||
value_variant_type.construct_from_field(output_ptr, std::move(output_field));
|
||||
params.output_set(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -347,12 +347,12 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
|
||||
else if (property.type == IDP_DOUBLE) {
|
||||
value = float(IDP_Double(&property));
|
||||
}
|
||||
new (r_value) bke::ValueOrField<float>(value);
|
||||
new (r_value) bke::SocketValueVariant<float>(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_INT: {
|
||||
int value = IDP_Int(&property);
|
||||
new (r_value) bke::ValueOrField<int>(value);
|
||||
new (r_value) bke::SocketValueVariant<int>(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_VECTOR: {
|
||||
@@ -368,7 +368,7 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
|
||||
BLI_assert(property.subtype == IDP_DOUBLE);
|
||||
value = float3(double3(static_cast<const double *>(property_array)));
|
||||
}
|
||||
new (r_value) bke::ValueOrField<float3>(value);
|
||||
new (r_value) bke::SocketValueVariant<float3>(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_RGBA: {
|
||||
@@ -385,12 +385,12 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
|
||||
vec = float4(double4(static_cast<const double *>(property_array)));
|
||||
}
|
||||
ColorGeometry4f value(vec);
|
||||
new (r_value) bke::ValueOrField<ColorGeometry4f>(value);
|
||||
new (r_value) bke::SocketValueVariant<ColorGeometry4f>(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_BOOLEAN: {
|
||||
const bool value = IDP_Bool(&property);
|
||||
new (r_value) bke::ValueOrField<bool>(value);
|
||||
new (r_value) bke::SocketValueVariant<bool>(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_ROTATION: {
|
||||
@@ -407,12 +407,12 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
|
||||
vec = float3(double3(static_cast<const double *>(property_array)));
|
||||
}
|
||||
const math::EulerXYZ euler_value = math::EulerXYZ(vec);
|
||||
new (r_value) bke::ValueOrField<math::Quaternion>(math::to_quaternion(euler_value));
|
||||
new (r_value) bke::SocketValueVariant<math::Quaternion>(math::to_quaternion(euler_value));
|
||||
break;
|
||||
}
|
||||
case SOCK_STRING: {
|
||||
std::string value = IDP_String(&property);
|
||||
new (r_value) bke::ValueOrField<std::string>(std::move(value));
|
||||
new (r_value) bke::SocketValueVariant<std::string>(std::move(value));
|
||||
break;
|
||||
}
|
||||
case SOCK_OBJECT: {
|
||||
@@ -509,10 +509,10 @@ static void initialize_group_input(const bNodeTree &tree,
|
||||
if (attribute_name && bke::allow_procedural_attribute_access(*attribute_name)) {
|
||||
fn::GField attribute_field = bke::AttributeFieldInput::Create(*attribute_name,
|
||||
*typeinfo->base_cpp_type);
|
||||
const auto *value_or_field_cpp_type = bke::ValueOrFieldCPPType::get_from_self(
|
||||
const auto *value_variant_type = bke::SocketValueVariantCPPType::get_from_self(
|
||||
*typeinfo->geometry_nodes_cpp_type);
|
||||
BLI_assert(value_or_field_cpp_type != nullptr);
|
||||
value_or_field_cpp_type->construct_from_field(r_value, std::move(attribute_field));
|
||||
BLI_assert(value_variant_type != nullptr);
|
||||
value_variant_type->construct_from_field(r_value, std::move(attribute_field));
|
||||
}
|
||||
else if (is_layer_selection_field(io_input)) {
|
||||
const IDProperty *property_layer_name = IDP_GetPropertyFromGroup(properties,
|
||||
@@ -520,10 +520,10 @@ static void initialize_group_input(const bNodeTree &tree,
|
||||
StringRef layer_name = IDP_String(property_layer_name);
|
||||
const fn::GField selection_field(
|
||||
std::make_shared<bke::NamedLayerSelectionFieldInput>(layer_name), 0);
|
||||
const auto *value_or_field_cpp_type = bke::ValueOrFieldCPPType::get_from_self(
|
||||
const auto *value_variant_type = bke::SocketValueVariantCPPType::get_from_self(
|
||||
*typeinfo->geometry_nodes_cpp_type);
|
||||
BLI_assert(value_or_field_cpp_type != nullptr);
|
||||
value_or_field_cpp_type->construct_from_field(r_value, std::move(selection_field));
|
||||
BLI_assert(value_variant_type != nullptr);
|
||||
value_variant_type->construct_from_field(r_value, std::move(selection_field));
|
||||
}
|
||||
else {
|
||||
init_socket_cpp_value_from_property(*property, socket_data_type, r_value);
|
||||
@@ -571,9 +571,9 @@ static MultiValueMap<eAttrDomain, OutputAttributeInfo> find_output_attributes_to
|
||||
|
||||
const int index = socket->index();
|
||||
const GPointer value = output_values[index];
|
||||
const auto *value_or_field_type = bke::ValueOrFieldCPPType::get_from_self(*value.type());
|
||||
BLI_assert(value_or_field_type != nullptr);
|
||||
const fn::GField field = value_or_field_type->as_field(value.get());
|
||||
const auto *value_variant_type = bke::SocketValueVariantCPPType::get_from_self(*value.type());
|
||||
BLI_assert(value_variant_type != nullptr);
|
||||
const fn::GField field = value_variant_type->as_field(value.get());
|
||||
|
||||
const bNodeTreeInterfaceSocket *interface_socket = tree.interface_outputs()[index];
|
||||
const eAttrDomain domain = (eAttrDomain)interface_socket->attribute_domain;
|
||||
|
||||
@@ -57,8 +57,8 @@ namespace blender::nodes {
|
||||
namespace aai = bke::anonymous_attribute_inferencing;
|
||||
using bke::bNodeTreeZone;
|
||||
using bke::bNodeTreeZones;
|
||||
using bke::ValueOrField;
|
||||
using bke::ValueOrFieldCPPType;
|
||||
using bke::SocketValueVariant;
|
||||
using bke::SocketValueVariantCPPType;
|
||||
|
||||
static const CPPType *get_socket_cpp_type(const bNodeSocketType &typeinfo)
|
||||
{
|
||||
@@ -342,14 +342,14 @@ class LazyFunctionForGeometryNode : public LazyFunction {
|
||||
const int lf_index,
|
||||
AnonymousAttributeIDPtr attribute_id) const
|
||||
{
|
||||
const ValueOrFieldCPPType &value_or_field_cpp_type = *ValueOrFieldCPPType::get_from_self(
|
||||
*outputs_[lf_index].type);
|
||||
const SocketValueVariantCPPType &value_variant_type =
|
||||
*SocketValueVariantCPPType::get_from_self(*outputs_[lf_index].type);
|
||||
GField output_field{std::make_shared<AnonymousAttributeFieldInput>(
|
||||
std::move(attribute_id),
|
||||
value_or_field_cpp_type.value,
|
||||
value_variant_type.value,
|
||||
fmt::format(TIP_("{} node"), std::string_view(node_.label_or_name())))};
|
||||
void *r_value = params.get_output_data_ptr(lf_index);
|
||||
value_or_field_cpp_type.construct_from_field(r_value, std::move(output_field));
|
||||
value_variant_type.construct_from_field(r_value, std::move(output_field));
|
||||
params.output_set(lf_index);
|
||||
}
|
||||
|
||||
@@ -415,21 +415,22 @@ class LazyFunctionForMultiInput : public LazyFunction {
|
||||
{
|
||||
/* Currently we only have multi-inputs for geometry and string sockets. This could be
|
||||
* generalized in the future. */
|
||||
base_type_->to_static_type_tag<GeometrySet, ValueOrField<std::string>>([&](auto type_tag) {
|
||||
using T = typename decltype(type_tag)::type;
|
||||
if constexpr (std::is_void_v<T>) {
|
||||
/* This type is not supported in this node for now. */
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
else {
|
||||
void *output_ptr = params.get_output_data_ptr(0);
|
||||
Vector<T> &values = *new (output_ptr) Vector<T>();
|
||||
for (const int i : inputs_.index_range()) {
|
||||
values.append(params.extract_input<T>(i));
|
||||
}
|
||||
params.output_set(0);
|
||||
}
|
||||
});
|
||||
base_type_->to_static_type_tag<GeometrySet, SocketValueVariant<std::string>>(
|
||||
[&](auto type_tag) {
|
||||
using T = typename decltype(type_tag)::type;
|
||||
if constexpr (std::is_void_v<T>) {
|
||||
/* This type is not supported in this node for now. */
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
else {
|
||||
void *output_ptr = params.get_output_data_ptr(0);
|
||||
Vector<T> &values = *new (output_ptr) Vector<T>();
|
||||
for (const int i : inputs_.index_range()) {
|
||||
values.append(params.extract_input<T>(i));
|
||||
}
|
||||
params.output_set(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -481,11 +482,11 @@ class LazyFunctionForUndefinedNode : public LazyFunction {
|
||||
* Executes a multi-function. If all inputs are single values, the results will also be single
|
||||
* values. If any input is a field, the outputs will also be fields.
|
||||
*/
|
||||
static void execute_multi_function_on_value_or_field(
|
||||
static void execute_multi_function_on_value_variant(
|
||||
const MultiFunction &fn,
|
||||
const std::shared_ptr<MultiFunction> &owned_fn,
|
||||
const Span<const ValueOrFieldCPPType *> input_types,
|
||||
const Span<const ValueOrFieldCPPType *> output_types,
|
||||
const Span<const SocketValueVariantCPPType *> input_types,
|
||||
const Span<const SocketValueVariantCPPType *> output_types,
|
||||
const Span<const void *> input_values,
|
||||
const Span<void *> output_values)
|
||||
{
|
||||
@@ -496,9 +497,9 @@ static void execute_multi_function_on_value_or_field(
|
||||
/* Check if any input is a field. */
|
||||
bool any_input_is_field = false;
|
||||
for (const int i : input_types.index_range()) {
|
||||
const ValueOrFieldCPPType &type = *input_types[i];
|
||||
const void *value_or_field = input_values[i];
|
||||
if (type.is_field(value_or_field)) {
|
||||
const SocketValueVariantCPPType &type = *input_types[i];
|
||||
const void *value_variant = input_values[i];
|
||||
if (type.is_field(value_variant)) {
|
||||
any_input_is_field = true;
|
||||
break;
|
||||
}
|
||||
@@ -508,9 +509,9 @@ static void execute_multi_function_on_value_or_field(
|
||||
/* Convert all inputs into fields, so that they can be used as input in the new field. */
|
||||
Vector<GField> input_fields;
|
||||
for (const int i : input_types.index_range()) {
|
||||
const ValueOrFieldCPPType &type = *input_types[i];
|
||||
const void *value_or_field = input_values[i];
|
||||
input_fields.append(type.as_field(value_or_field));
|
||||
const SocketValueVariantCPPType &type = *input_types[i];
|
||||
const void *value_variant = input_values[i];
|
||||
input_fields.append(type.as_field(value_variant));
|
||||
}
|
||||
|
||||
/* Construct the new field node. */
|
||||
@@ -524,9 +525,9 @@ static void execute_multi_function_on_value_or_field(
|
||||
|
||||
/* Store the new fields in the output. */
|
||||
for (const int i : output_types.index_range()) {
|
||||
const ValueOrFieldCPPType &type = *output_types[i];
|
||||
void *value_or_field = output_values[i];
|
||||
type.construct_from_field(value_or_field, GField{operation, i});
|
||||
const SocketValueVariantCPPType &type = *output_types[i];
|
||||
void *value_variant = output_values[i];
|
||||
type.construct_from_field(value_variant, GField{operation, i});
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -536,16 +537,16 @@ static void execute_multi_function_on_value_or_field(
|
||||
mf::ContextBuilder context;
|
||||
|
||||
for (const int i : input_types.index_range()) {
|
||||
const ValueOrFieldCPPType &type = *input_types[i];
|
||||
const void *value_or_field = input_values[i];
|
||||
const void *value = type.get_value_ptr(value_or_field);
|
||||
const SocketValueVariantCPPType &type = *input_types[i];
|
||||
const void *value_variant = input_values[i];
|
||||
const void *value = type.get_value_ptr(value_variant);
|
||||
params.add_readonly_single_input(GPointer{type.value, value});
|
||||
}
|
||||
for (const int i : output_types.index_range()) {
|
||||
const ValueOrFieldCPPType &type = *output_types[i];
|
||||
void *value_or_field = output_values[i];
|
||||
type.self.default_construct(value_or_field);
|
||||
void *value = type.get_value_ptr(value_or_field);
|
||||
const SocketValueVariantCPPType &type = *output_types[i];
|
||||
void *value_variant = output_values[i];
|
||||
type.self.default_construct(value_variant);
|
||||
void *value = type.get_value_ptr(value_variant);
|
||||
type.value.destruct(value);
|
||||
params.add_uninitialized_single_output(GMutableSpan{type.value, value, 1});
|
||||
}
|
||||
@@ -620,13 +621,13 @@ class LazyFunctionForMutedNode : public LazyFunction {
|
||||
}
|
||||
/* Perform a type conversion and then format the value. */
|
||||
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
|
||||
const auto *from_type = ValueOrFieldCPPType::get_from_self(input_type);
|
||||
const auto *to_type = ValueOrFieldCPPType::get_from_self(output_type);
|
||||
const auto *from_type = SocketValueVariantCPPType::get_from_self(input_type);
|
||||
const auto *to_type = SocketValueVariantCPPType::get_from_self(output_type);
|
||||
if (from_type != nullptr && to_type != nullptr) {
|
||||
if (conversions.is_convertible(from_type->value, to_type->value)) {
|
||||
const MultiFunction &multi_fn = *conversions.get_conversion_multi_function(
|
||||
mf::DataType::ForSingle(from_type->value), mf::DataType::ForSingle(to_type->value));
|
||||
execute_multi_function_on_value_or_field(
|
||||
execute_multi_function_on_value_variant(
|
||||
multi_fn, {}, {from_type}, {to_type}, {input_value}, {output_value});
|
||||
}
|
||||
params.output_set(output_i);
|
||||
@@ -646,13 +647,13 @@ class LazyFunctionForMutedNode : public LazyFunction {
|
||||
class LazyFunctionForMultiFunctionConversion : public LazyFunction {
|
||||
private:
|
||||
const MultiFunction &fn_;
|
||||
const ValueOrFieldCPPType &from_type_;
|
||||
const ValueOrFieldCPPType &to_type_;
|
||||
const SocketValueVariantCPPType &from_type_;
|
||||
const SocketValueVariantCPPType &to_type_;
|
||||
|
||||
public:
|
||||
LazyFunctionForMultiFunctionConversion(const MultiFunction &fn,
|
||||
const ValueOrFieldCPPType &from,
|
||||
const ValueOrFieldCPPType &to)
|
||||
const SocketValueVariantCPPType &from,
|
||||
const SocketValueVariantCPPType &to)
|
||||
: fn_(fn), from_type_(from), to_type_(to)
|
||||
{
|
||||
debug_name_ = "Convert";
|
||||
@@ -667,7 +668,7 @@ class LazyFunctionForMultiFunctionConversion : public LazyFunction {
|
||||
BLI_assert(from_value != nullptr);
|
||||
BLI_assert(to_value != nullptr);
|
||||
|
||||
execute_multi_function_on_value_or_field(
|
||||
execute_multi_function_on_value_variant(
|
||||
fn_, {}, {&from_type_}, {&to_type_}, {from_value}, {to_value});
|
||||
|
||||
params.output_set(0);
|
||||
@@ -680,8 +681,8 @@ class LazyFunctionForMultiFunctionConversion : public LazyFunction {
|
||||
class LazyFunctionForMultiFunctionNode : public LazyFunction {
|
||||
private:
|
||||
const NodeMultiFunctions::Item fn_item_;
|
||||
Vector<const ValueOrFieldCPPType *> input_types_;
|
||||
Vector<const ValueOrFieldCPPType *> output_types_;
|
||||
Vector<const SocketValueVariantCPPType *> input_types_;
|
||||
Vector<const SocketValueVariantCPPType *> output_types_;
|
||||
|
||||
public:
|
||||
LazyFunctionForMultiFunctionNode(const bNode &node,
|
||||
@@ -693,10 +694,10 @@ class LazyFunctionForMultiFunctionNode : public LazyFunction {
|
||||
debug_name_ = node.name;
|
||||
lazy_function_interface_from_node(node, inputs_, outputs_, r_lf_index_by_bsocket);
|
||||
for (const lf::Input &fn_input : inputs_) {
|
||||
input_types_.append(ValueOrFieldCPPType::get_from_self(*fn_input.type));
|
||||
input_types_.append(SocketValueVariantCPPType::get_from_self(*fn_input.type));
|
||||
}
|
||||
for (const lf::Output &fn_output : outputs_) {
|
||||
output_types_.append(ValueOrFieldCPPType::get_from_self(*fn_output.type));
|
||||
output_types_.append(SocketValueVariantCPPType::get_from_self(*fn_output.type));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,7 +711,7 @@ class LazyFunctionForMultiFunctionNode : public LazyFunction {
|
||||
for (const int i : outputs_.index_range()) {
|
||||
output_values[i] = params.get_output_data_ptr(i);
|
||||
}
|
||||
execute_multi_function_on_value_or_field(
|
||||
execute_multi_function_on_value_variant(
|
||||
*fn_item_.fn, fn_item_.owned_fn, input_types_, output_types_, input_values, output_values);
|
||||
for (const int i : outputs_.index_range()) {
|
||||
params.output_set(i);
|
||||
@@ -790,10 +791,10 @@ class LazyFunctionForViewerNode : public LazyFunction {
|
||||
const NodeGeometryViewer *storage = static_cast<NodeGeometryViewer *>(bnode_.storage);
|
||||
|
||||
if (use_field_input_) {
|
||||
const void *value_or_field = params.try_get_input_data_ptr(1);
|
||||
BLI_assert(value_or_field != nullptr);
|
||||
const auto &value_or_field_type = *ValueOrFieldCPPType::get_from_self(*inputs_[1].type);
|
||||
GField field = value_or_field_type.as_field(value_or_field);
|
||||
const void *value_variant = params.try_get_input_data_ptr(1);
|
||||
BLI_assert(value_variant != nullptr);
|
||||
const auto &value_variant_type = *SocketValueVariantCPPType::get_from_self(*inputs_[1].type);
|
||||
GField field = value_variant_type.as_field(value_variant);
|
||||
const eAttrDomain domain = eAttrDomain(storage->domain);
|
||||
const StringRefNull viewer_attribute_name = ".viewer";
|
||||
if (domain == ATTR_DOMAIN_INSTANCE) {
|
||||
@@ -1099,14 +1100,14 @@ class LazyFunctionForSwitchSocketUsage : public lf::LazyFunction {
|
||||
LazyFunctionForSwitchSocketUsage()
|
||||
{
|
||||
debug_name_ = "Switch Socket Usage";
|
||||
inputs_.append_as("Condition", CPPType::get<ValueOrField<bool>>());
|
||||
inputs_.append_as("Condition", CPPType::get<SocketValueVariant<bool>>());
|
||||
outputs_.append_as("False", CPPType::get<bool>());
|
||||
outputs_.append_as("True", CPPType::get<bool>());
|
||||
}
|
||||
|
||||
void execute_impl(lf::Params ¶ms, const lf::Context & /*context*/) const override
|
||||
{
|
||||
const ValueOrField<bool> &condition = params.get_input<ValueOrField<bool>>(0);
|
||||
const SocketValueVariant<bool> &condition = params.get_input<SocketValueVariant<bool>>(0);
|
||||
if (condition.is_field()) {
|
||||
params.set_output(0, true);
|
||||
params.set_output(1, true);
|
||||
@@ -1128,7 +1129,7 @@ class LazyFunctionForIndexSwitchSocketUsage : public lf::LazyFunction {
|
||||
LazyFunctionForIndexSwitchSocketUsage(const bNode &bnode)
|
||||
{
|
||||
debug_name_ = "Index Switch Socket Usage";
|
||||
inputs_.append_as("Index", CPPType::get<ValueOrField<int>>());
|
||||
inputs_.append_as("Index", CPPType::get<SocketValueVariant<int>>());
|
||||
for (const bNodeSocket *socket : bnode.input_sockets().drop_front(1)) {
|
||||
outputs_.append_as(socket->identifier, CPPType::get<bool>());
|
||||
}
|
||||
@@ -1136,7 +1137,7 @@ class LazyFunctionForIndexSwitchSocketUsage : public lf::LazyFunction {
|
||||
|
||||
void execute_impl(lf::Params ¶ms, const lf::Context & /*context*/) const override
|
||||
{
|
||||
const ValueOrField<int> &index = params.get_input<ValueOrField<int>>(0);
|
||||
const SocketValueVariant<int> &index = params.get_input<SocketValueVariant<int>>(0);
|
||||
if (index.is_field()) {
|
||||
for (const int i : outputs_.index_range()) {
|
||||
params.set_output(i, true);
|
||||
@@ -1156,10 +1157,10 @@ class LazyFunctionForIndexSwitchSocketUsage : public lf::LazyFunction {
|
||||
*/
|
||||
class LazyFunctionForAnonymousAttributeSetExtract : public lf::LazyFunction {
|
||||
private:
|
||||
const ValueOrFieldCPPType &type_;
|
||||
const SocketValueVariantCPPType &type_;
|
||||
|
||||
public:
|
||||
LazyFunctionForAnonymousAttributeSetExtract(const ValueOrFieldCPPType &type) : type_(type)
|
||||
LazyFunctionForAnonymousAttributeSetExtract(const SocketValueVariantCPPType &type) : type_(type)
|
||||
{
|
||||
debug_name_ = "Extract Attribute Set";
|
||||
inputs_.append_as("Use", CPPType::get<bool>());
|
||||
@@ -1174,15 +1175,15 @@ class LazyFunctionForAnonymousAttributeSetExtract : public lf::LazyFunction {
|
||||
params.set_output<bke::AnonymousAttributeSet>(0, {});
|
||||
return;
|
||||
}
|
||||
const void *value_or_field = params.try_get_input_data_ptr_or_request(1);
|
||||
if (value_or_field == nullptr) {
|
||||
const void *value_variant = params.try_get_input_data_ptr_or_request(1);
|
||||
if (value_variant == nullptr) {
|
||||
/* Wait until the field is computed. */
|
||||
return;
|
||||
}
|
||||
|
||||
bke::AnonymousAttributeSet attributes;
|
||||
if (type_.is_field(value_or_field)) {
|
||||
const GField &field = *type_.get_field_ptr(value_or_field);
|
||||
if (type_.is_field(value_variant)) {
|
||||
const GField &field = *type_.get_field_ptr(value_variant);
|
||||
field.node().for_each_field_input_recursive([&](const FieldInput &field_input) {
|
||||
if (const auto *attr_field_input = dynamic_cast<const AnonymousAttributeFieldInput *>(
|
||||
&field_input))
|
||||
@@ -1528,7 +1529,7 @@ class LazyFunctionForRepeatZone : public LazyFunction {
|
||||
{
|
||||
debug_name_ = "Repeat Zone";
|
||||
|
||||
inputs_.append_as("Iterations", CPPType::get<ValueOrField<int>>(), lf::ValueUsage::Used);
|
||||
inputs_.append_as("Iterations", CPPType::get<SocketValueVariant<int>>(), lf::ValueUsage::Used);
|
||||
for (const bNodeSocket *socket : zone.input_node->input_sockets().drop_front(1).drop_back(1)) {
|
||||
inputs_.append_as(
|
||||
socket->name, *socket->typeinfo->geometry_nodes_cpp_type, lf::ValueUsage::Maybe);
|
||||
@@ -1641,7 +1642,8 @@ class LazyFunctionForRepeatZone : public LazyFunction {
|
||||
|
||||
/* Number of iterations to evaluate. */
|
||||
const int iterations = std::max<int>(
|
||||
0, params.get_input<ValueOrField<int>>(zone_info_.indices.inputs.main[0]).as_value());
|
||||
0,
|
||||
params.get_input<SocketValueVariant<int>>(zone_info_.indices.inputs.main[0]).as_value());
|
||||
|
||||
/* Show a warning when the inspection index is out of range. */
|
||||
if (node_storage.inspection_index > 0) {
|
||||
@@ -2853,7 +2855,8 @@ struct GeometryNodesLazyFunctionBuilder {
|
||||
lf::Graph &lf_graph,
|
||||
Set<lf::InputSocket *> &socket_usage_inputs)
|
||||
{
|
||||
const ValueOrFieldCPPType &type = *ValueOrFieldCPPType::get_from_self(lf_field_socket.type());
|
||||
const SocketValueVariantCPPType &type = *SocketValueVariantCPPType::get_from_self(
|
||||
lf_field_socket.type());
|
||||
auto &lazy_function = scope_.construct<LazyFunctionForAnonymousAttributeSetExtract>(type);
|
||||
lf::Node &lf_node = lf_graph.add_function(lazy_function);
|
||||
lf::InputSocket &lf_use_input = lf_node.input(0);
|
||||
@@ -3781,15 +3784,15 @@ struct GeometryNodesLazyFunctionBuilder {
|
||||
if (from_type == to_type) {
|
||||
return &from_socket;
|
||||
}
|
||||
const auto *from_field_type = ValueOrFieldCPPType::get_from_self(from_type);
|
||||
const auto *to_field_type = ValueOrFieldCPPType::get_from_self(to_type);
|
||||
if (from_field_type != nullptr && to_field_type != nullptr) {
|
||||
if (conversions_->is_convertible(from_field_type->value, to_field_type->value)) {
|
||||
const auto *from_variant_type = SocketValueVariantCPPType::get_from_self(from_type);
|
||||
const auto *to_variant_type = SocketValueVariantCPPType::get_from_self(to_type);
|
||||
if (from_variant_type != nullptr && to_variant_type != nullptr) {
|
||||
if (conversions_->is_convertible(from_variant_type->value, to_variant_type->value)) {
|
||||
const MultiFunction &multi_fn = *conversions_->get_conversion_multi_function(
|
||||
mf::DataType::ForSingle(from_field_type->value),
|
||||
mf::DataType::ForSingle(to_field_type->value));
|
||||
mf::DataType::ForSingle(from_variant_type->value),
|
||||
mf::DataType::ForSingle(to_variant_type->value));
|
||||
auto &fn = scope_.construct<LazyFunctionForMultiFunctionConversion>(
|
||||
multi_fn, *from_field_type, *to_field_type);
|
||||
multi_fn, *from_variant_type, *to_variant_type);
|
||||
lf::Node &conversion_node = lf_graph.add_function(fn);
|
||||
lf_graph.add_link(from_socket, conversion_node.input(0));
|
||||
return &conversion_node.output(0);
|
||||
|
||||
@@ -180,11 +180,11 @@ void GeoTreeLogger::log_value(const bNode &node, const bNodeSocket &socket, cons
|
||||
const bke::GeometrySet &geometry = *value.get<bke::GeometrySet>();
|
||||
store_logged_value(this->allocator->construct<GeometryInfoLog>(geometry));
|
||||
}
|
||||
else if (const auto *value_or_field_type = bke::ValueOrFieldCPPType::get_from_self(type)) {
|
||||
const void *value_or_field = value.get();
|
||||
const CPPType &base_type = value_or_field_type->value;
|
||||
if (value_or_field_type->is_field(value_or_field)) {
|
||||
const GField *field = value_or_field_type->get_field_ptr(value_or_field);
|
||||
else if (const auto *value_variant_type = bke::SocketValueVariantCPPType::get_from_self(type)) {
|
||||
const void *value_variant = value.get();
|
||||
const CPPType &base_type = value_variant_type->value;
|
||||
if (value_variant_type->is_field(value_variant)) {
|
||||
const GField *field = value_variant_type->get_field_ptr(value_variant);
|
||||
if (field->node().depends_on_input()) {
|
||||
store_logged_value(this->allocator->construct<FieldInfoLog>(*field));
|
||||
}
|
||||
@@ -195,7 +195,7 @@ void GeoTreeLogger::log_value(const bNode &node, const bNodeSocket &socket, cons
|
||||
}
|
||||
}
|
||||
else {
|
||||
const void *value = value_or_field_type->get_value_ptr(value_or_field);
|
||||
const void *value = value_variant_type->get_value_ptr(value_variant);
|
||||
log_generic_value(base_type, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,24 +888,26 @@ namespace implicit_field_inputs {
|
||||
|
||||
void position(const bNode & /*node*/, void *r_value)
|
||||
{
|
||||
new (r_value) bke::ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>("position"));
|
||||
new (r_value)
|
||||
bke::SocketValueVariant<float3>(bke::AttributeFieldInput::Create<float3>("position"));
|
||||
}
|
||||
|
||||
void normal(const bNode & /*node*/, void *r_value)
|
||||
{
|
||||
new (r_value)
|
||||
bke::ValueOrField<float3>(fn::Field<float3>(std::make_shared<bke::NormalFieldInput>()));
|
||||
new (r_value) bke::SocketValueVariant<float3>(
|
||||
fn::Field<float3>(std::make_shared<bke::NormalFieldInput>()));
|
||||
}
|
||||
|
||||
void index(const bNode & /*node*/, void *r_value)
|
||||
{
|
||||
new (r_value) bke::ValueOrField<int>(fn::Field<int>(std::make_shared<fn::IndexFieldInput>()));
|
||||
new (r_value)
|
||||
bke::SocketValueVariant<int>(fn::Field<int>(std::make_shared<fn::IndexFieldInput>()));
|
||||
}
|
||||
|
||||
void id_or_index(const bNode & /*node*/, void *r_value)
|
||||
{
|
||||
new (r_value)
|
||||
bke::ValueOrField<int>(fn::Field<int>(std::make_shared<bke::IDAttributeFieldInput>()));
|
||||
bke::SocketValueVariant<int>(fn::Field<int>(std::make_shared<bke::IDAttributeFieldInput>()));
|
||||
}
|
||||
|
||||
} // namespace implicit_field_inputs
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include "NOD_socket_declarations.hh"
|
||||
|
||||
using namespace blender;
|
||||
using blender::bke::ValueOrField;
|
||||
using blender::bke::SocketValueVariant;
|
||||
using blender::nodes::SocketDeclarationPtr;
|
||||
|
||||
bNodeSocket *node_add_socket_from_template(bNodeTree *ntree,
|
||||
@@ -950,10 +950,10 @@ static bNodeSocketType *make_socket_type_bool()
|
||||
socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
*(bool *)r_value = ((bNodeSocketValueBoolean *)socket_value)->value;
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<bool>>();
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<SocketValueVariant<bool>>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
const bool value = ((bNodeSocketValueBoolean *)socket_value)->value;
|
||||
new (r_value) ValueOrField<bool>(value);
|
||||
new (r_value) SocketValueVariant<bool>(value);
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
@@ -967,12 +967,13 @@ static bNodeSocketType *make_socket_type_rotation()
|
||||
const math::EulerXYZ euler(float3(typed_value.value_euler));
|
||||
*static_cast<math::Quaternion *>(r_value) = math::to_quaternion(euler);
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<math::Quaternion>>();
|
||||
socktype->geometry_nodes_cpp_type =
|
||||
&blender::CPPType::get<SocketValueVariant<math::Quaternion>>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
const auto &typed_value = *(bNodeSocketValueRotation *)socket_value;
|
||||
const math::EulerXYZ euler(float3(typed_value.value_euler));
|
||||
const math::Quaternion value = math::to_quaternion(euler);
|
||||
new (r_value) ValueOrField<math::Quaternion>(value);
|
||||
new (r_value) SocketValueVariant<math::Quaternion>(value);
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
@@ -984,10 +985,10 @@ static bNodeSocketType *make_socket_type_float(PropertySubType subtype)
|
||||
socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
*(float *)r_value = ((bNodeSocketValueFloat *)socket_value)->value;
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<float>>();
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<SocketValueVariant<float>>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
const float value = ((bNodeSocketValueFloat *)socket_value)->value;
|
||||
new (r_value) ValueOrField<float>(value);
|
||||
new (r_value) SocketValueVariant<float>(value);
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
@@ -999,10 +1000,10 @@ static bNodeSocketType *make_socket_type_int(PropertySubType subtype)
|
||||
socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
*(int *)r_value = ((bNodeSocketValueInt *)socket_value)->value;
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<int>>();
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<SocketValueVariant<int>>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
const int value = ((bNodeSocketValueInt *)socket_value)->value;
|
||||
new (r_value) ValueOrField<int>(value);
|
||||
new (r_value) SocketValueVariant<int>(value);
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
@@ -1014,10 +1015,11 @@ static bNodeSocketType *make_socket_type_vector(PropertySubType subtype)
|
||||
socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
*(blender::float3 *)r_value = ((bNodeSocketValueVector *)socket_value)->value;
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<blender::float3>>();
|
||||
socktype->geometry_nodes_cpp_type =
|
||||
&blender::CPPType::get<SocketValueVariant<blender::float3>>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
const blender::float3 value = ((bNodeSocketValueVector *)socket_value)->value;
|
||||
new (r_value) ValueOrField<blender::float3>(value);
|
||||
new (r_value) SocketValueVariant<blender::float3>(value);
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
@@ -1030,10 +1032,10 @@ static bNodeSocketType *make_socket_type_rgba()
|
||||
*(blender::ColorGeometry4f *)r_value = ((bNodeSocketValueRGBA *)socket_value)->value;
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type =
|
||||
&blender::CPPType::get<ValueOrField<blender::ColorGeometry4f>>();
|
||||
&blender::CPPType::get<SocketValueVariant<blender::ColorGeometry4f>>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
const blender::ColorGeometry4f value = ((bNodeSocketValueRGBA *)socket_value)->value;
|
||||
new (r_value) ValueOrField<blender::ColorGeometry4f>(value);
|
||||
new (r_value) SocketValueVariant<blender::ColorGeometry4f>(value);
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
@@ -1045,12 +1047,12 @@ static bNodeSocketType *make_socket_type_string()
|
||||
socktype->get_base_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
new (r_value) std::string(((bNodeSocketValueString *)socket_value)->value);
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<std::string>>();
|
||||
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<SocketValueVariant<std::string>>();
|
||||
socktype->get_geometry_nodes_cpp_value = [](const void *socket_value, void *r_value) {
|
||||
std::string value;
|
||||
value.~basic_string();
|
||||
new (&value) std::string(((bNodeSocketValueString *)socket_value)->value);
|
||||
new (r_value) ValueOrField<std::string>(value);
|
||||
new (r_value) SocketValueVariant<std::string>(value);
|
||||
};
|
||||
return socktype;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user