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:
Jacques Lucke
2023-12-13 13:40:40 +01:00
parent 1a4f4104d1
commit 3370228ae8
18 changed files with 254 additions and 242 deletions

View File

@@ -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;
}

View File

@@ -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>()

View File

@@ -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;

View File

@@ -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>);
}

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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 &params, 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);
}
};

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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));
}
}

View File

@@ -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));

View File

@@ -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;

View File

@@ -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 &params, 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 &params) 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);
}

View File

@@ -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;

View File

@@ -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 &params, 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 &params, 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);

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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;
}