Refactor: Geometry Nodes: remove AnonymousAttributeID in favor of just strings

This removes `AnonymousAttributeID` which was "attached" to every anonymous
attribute before. It adds more complexity than is justified for its
functionality.

It was originally introduced to keep the reference count of the anonymous
attribute so that it can be deleted automatically when the attribute is not
referenced anymore. For quite some time we have had deterministic attribute
life-times though which don't rely on the reference count anymore.

Anonymous attributes are sometimes shown in the UI as "friendly looking" string
like `"UV Map" from Cube`. Some information necessary for this was also stored
in `AnonymousAttributeID`. However, this can also be solved differently.
Specifically, this functionality has now been added directly to
`AttributeFieldInput`.

This refactor also allows removing `AttributeIDRef` which was mainly introduced
because we had to keep the `AnonymousAttributeID` attached with the attribute
name. Just using simple string types to identify attributes can reduce the
mental overhead quite significantly. This will be done as a separate refactor
though.

Pull Request: https://projects.blender.org/blender/blender/pulls/127081
This commit is contained in:
Jacques Lucke
2024-09-03 15:38:51 +02:00
parent b2a0d29345
commit b279a6d703
57 changed files with 293 additions and 541 deletions

View File

@@ -12,52 +12,6 @@
namespace blender::bke {
/**
* An #AnonymousAttributeID contains information about a specific anonymous attribute.
* Like normal attributes, anonymous attributes are also identified by their name, so one should
* not have to compare #AnonymousAttributeID pointers.
*
* Anonymous attributes don't need additional information besides their name, with a few
* exceptions:
* - The name of anonymous attributes is generated automatically, so it is generally not human
* readable (just random characters). #AnonymousAttributeID can provide more context as where a
* specific anonymous attribute was created which can simplify debugging.
* - [Not yet supported.] When anonymous attributes are contained in on-disk caches, we have to map
* those back to anonymous attributes at run-time. The issue is that (for various reasons) we
* might change how anonymous attribute names are generated in the future, which would lead to a
* mis-match between stored and new attribute names. To work around it, we should cache
* additional information for anonymous attributes on disk (like which node created it). This
* information can then be used to map stored attributes to their run-time counterpart.
*
* Once created, #AnonymousAttributeID is immutable. Also it is intrinsically reference counted so
* that it can have shared ownership. `std::shared_ptr` can't be used for that purpose here,
* because that is not available in C code. If possible, the #AnonymousAttributeIDPtr wrapper
* should be used to avoid manual reference counting in C++ code.
*/
class AnonymousAttributeID : public ImplicitSharingMixin {
protected:
std::string name_;
public:
virtual ~AnonymousAttributeID() = default;
StringRefNull name() const
{
return name_;
}
virtual std::string user_name() const;
private:
void delete_self() override
{
MEM_delete(this);
}
};
/** Wrapper for #AnonymousAttributeID that avoids manual reference counting. */
using AnonymousAttributeIDPtr = ImplicitSharingPtr<const AnonymousAttributeID>;
/**
* A set of anonymous attribute names that is passed around in geometry nodes.
*/
@@ -91,7 +45,7 @@ class AnonymousAttributePropagationInfo {
/**
* Return true when the anonymous attribute should be propagated and false otherwise.
*/
bool propagate(const AnonymousAttributeID &anonymous_id) const;
bool propagate(StringRef anonymous_id) const;
};
} // namespace blender::bke

View File

@@ -0,0 +1,20 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include <fmt/format.h>
#include <sstream>
#include <xxhash.h>
namespace blender::bke {
template<typename... Args> inline std::string hash_to_anonymous_attribute_name(Args &&...args)
{
std::stringstream ss;
((ss << args), ...);
const std::string long_name = ss.str();
const XXH128_hash_t hash = XXH3_128bits(long_name.c_str(), long_name.size());
return fmt::format(".a_{:x}{:x}", hash.low64, hash.high64);
}
} // namespace blender::bke

View File

@@ -55,7 +55,6 @@ enum class AttrDomain : int8_t {
class AttributeIDRef {
private:
StringRef name_;
const AnonymousAttributeID *anonymous_id_ = nullptr;
public:
AttributeIDRef();
@@ -63,20 +62,29 @@ class AttributeIDRef {
AttributeIDRef(StringRefNull name);
AttributeIDRef(const char *name);
AttributeIDRef(const std::string &name);
AttributeIDRef(const AnonymousAttributeID &anonymous_id);
AttributeIDRef(const AnonymousAttributeID *anonymous_id);
operator bool() const;
uint64_t hash() const;
bool is_anonymous() const;
StringRef name() const;
const AnonymousAttributeID &anonymous_id() const;
BLI_STRUCT_EQUALITY_OPERATORS_1(AttributeIDRef, name_)
friend std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_id);
};
/**
* Checks if the attribute name has the `.a_` prefix which indicates that it is an anonymous
* attribute. I.e. it is just internally used by Blender and the name should not be exposed to the
* user.
*
* Use #hash_to_anonymous_attribute_name to generate names for anonymous attributes.
*/
inline bool attribute_name_is_anonymous(const StringRef name)
{
return name.startswith(".a_");
}
const CPPType *custom_data_type_to_cpp_type(eCustomDataType type);
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type);
@@ -862,19 +870,6 @@ inline AttributeIDRef::AttributeIDRef(const char *name) : name_(name) {}
inline AttributeIDRef::AttributeIDRef(const std::string &name) : name_(name) {}
/* The anonymous id is only borrowed, the caller has to keep a reference to it. */
inline AttributeIDRef::AttributeIDRef(const AnonymousAttributeID &anonymous_id)
: AttributeIDRef(anonymous_id.name())
{
anonymous_id_ = &anonymous_id;
}
inline AttributeIDRef::AttributeIDRef(const AnonymousAttributeID *anonymous_id)
: AttributeIDRef(anonymous_id ? anonymous_id->name() : "")
{
anonymous_id_ = anonymous_id;
}
inline AttributeIDRef::operator bool() const
{
return !name_.is_empty();
@@ -887,7 +882,7 @@ inline uint64_t AttributeIDRef::hash() const
inline bool AttributeIDRef::is_anonymous() const
{
return anonymous_id_ != nullptr;
return attribute_name_is_anonymous(name_);
}
inline StringRef AttributeIDRef::name() const
@@ -895,12 +890,6 @@ inline StringRef AttributeIDRef::name() const
return name_;
}
inline const AnonymousAttributeID &AttributeIDRef::anonymous_id() const
{
BLI_assert(this->is_anonymous());
return *anonymous_id_;
}
void gather_attributes(AttributeAccessor src_attributes,
AttrDomain domain,
const AnonymousAttributePropagationInfo &propagation_info,

View File

@@ -55,7 +55,7 @@ void move_bake_items_to_socket_values(
Span<BakeItem *> bake_items,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map,
FunctionRef<std::shared_ptr<AnonymousAttributeFieldInput>(int socket_index, const CPPType &)>
FunctionRef<std::shared_ptr<AttributeFieldInput>(int socket_index, const CPPType &)>
make_attribute_field,
Span<void *> r_socket_values);
@@ -67,8 +67,7 @@ void copy_bake_items_to_socket_values(
Span<const BakeItem *> bake_items,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map,
FunctionRef<std::shared_ptr<AnonymousAttributeFieldInput>(int, const CPPType &)>
make_attribute_field,
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
Span<void *> r_socket_values);
} // namespace blender::bke::bake

View File

@@ -282,19 +282,6 @@ const void *CustomData_add_layer_named_with_data(CustomData *data,
blender::StringRef name,
const blender::ImplicitSharingInfo *sharing_info);
void *CustomData_add_layer_anonymous(CustomData *data,
eCustomDataType type,
eCDAllocType alloctype,
int totelem,
const AnonymousAttributeIDHandle *anonymous_id);
const void *CustomData_add_layer_anonymous_with_data(
CustomData *data,
eCustomDataType type,
const AnonymousAttributeIDHandle *anonymous_id,
int totelem,
void *layer_data,
const blender::ImplicitSharingInfo *sharing_info);
/**
* Frees the active or first data layer with the give type.
* returns 1 on success, 0 if no layer with the given type is found

View File

@@ -261,22 +261,34 @@ class InstancesFieldInput : public fn::FieldInput {
class AttributeFieldInput : public GeometryFieldInput {
private:
std::string name_;
std::optional<std::string> socket_inspection_name_;
public:
AttributeFieldInput(std::string name, const CPPType &type)
: GeometryFieldInput(type, name), name_(std::move(name))
AttributeFieldInput(std::string name,
const CPPType &type,
std::optional<std::string> socket_inspection_name = std::nullopt)
: GeometryFieldInput(type, name),
name_(std::move(name)),
socket_inspection_name_(std::move(socket_inspection_name))
{
category_ = Category::NamedAttribute;
category_ = attribute_name_is_anonymous(name_) ? Category::AnonymousAttribute :
Category::NamedAttribute;
}
static fn::GField Create(std::string name, const CPPType &type)
static fn::GField Create(std::string name,
const CPPType &type,
std::optional<std::string> socket_inspection_name = std::nullopt)
{
auto field_input = std::make_shared<AttributeFieldInput>(std::move(name), type);
auto field_input = std::make_shared<AttributeFieldInput>(
std::move(name), type, std::move(socket_inspection_name));
return fn::GField(field_input);
}
template<typename T> static fn::Field<T> Create(std::string name)
template<typename T>
static fn::Field<T> Create(std::string name,
std::optional<std::string> socket_inspection_name = std::nullopt)
{
return fn::Field<T>(Create(std::move(name), CPPType::get<T>()));
return fn::Field<T>(
Create(std::move(name), CPPType::get<T>(), std::move(socket_inspection_name)));
}
StringRefNull attribute_name() const
@@ -371,46 +383,6 @@ class NormalFieldInput : public GeometryFieldInput {
bool is_equal_to(const fn::FieldNode &other) const override;
};
class AnonymousAttributeFieldInput : public GeometryFieldInput {
private:
AnonymousAttributeIDPtr anonymous_id_;
std::string producer_name_;
public:
AnonymousAttributeFieldInput(AnonymousAttributeIDPtr anonymous_id,
const CPPType &type,
std::string producer_name)
: GeometryFieldInput(type, anonymous_id->user_name()),
anonymous_id_(std::move(anonymous_id)),
producer_name_(std::move(producer_name))
{
category_ = Category::AnonymousAttribute;
}
template<typename T>
static fn::Field<T> Create(AnonymousAttributeIDPtr anonymous_id, std::string producer_name)
{
const CPPType &type = CPPType::get<T>();
auto field_input = std::make_shared<AnonymousAttributeFieldInput>(
std::move(anonymous_id), type, std::move(producer_name));
return fn::Field<T>{field_input};
}
const AnonymousAttributeIDPtr &anonymous_id() const
{
return anonymous_id_;
}
GVArray get_varray_for_context(const GeometryFieldContext &context,
const IndexMask &mask) const override;
std::string socket_inspection_name() const override;
uint64_t hash() const override;
bool is_equal_to(const fn::FieldNode &other) const override;
std::optional<AttrDomain> preferred_domain(const GeometryComponent &component) const override;
};
class CurveLengthFieldInput final : public CurvesFieldInput {
public:
CurveLengthFieldInput();

View File

@@ -328,6 +328,7 @@ set(SRC
BKE_anim_visualization.h
BKE_animsys.h
BKE_anonymous_attribute_id.hh
BKE_anonymous_attribute_make.hh
BKE_appdir.hh
BKE_armature.hh
BKE_asset.hh

View File

@@ -6,12 +6,7 @@
namespace blender::bke {
std::string AnonymousAttributeID::user_name() const
{
return this->name();
}
bool AnonymousAttributePropagationInfo::propagate(const AnonymousAttributeID &anonymous_id) const
bool AnonymousAttributePropagationInfo::propagate(const StringRef attribute) const
{
if (this->propagate_all) {
return true;
@@ -19,7 +14,7 @@ bool AnonymousAttributePropagationInfo::propagate(const AnonymousAttributeID &an
if (!this->names) {
return false;
}
return this->names->contains_as(anonymous_id.name());
return this->names->contains_as(attribute);
}
} // namespace blender::bke

View File

@@ -252,9 +252,6 @@ AttrDomain attribute_domain_highest_priority(Span<AttrDomain> domains)
static AttributeIDRef attribute_id_from_custom_data_layer(const CustomDataLayer &layer)
{
if (layer.anonymous_id != nullptr) {
return *layer.anonymous_id;
}
return layer.name;
}
@@ -264,15 +261,10 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
const int domain_size,
const AttributeIDRef &attribute_id)
{
if (!attribute_id.is_anonymous()) {
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
&custom_data, data_type, alloctype, domain_size, attribute_name_c);
}
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous(
&custom_data, data_type, alloctype, domain_size, &anonymous_id);
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
&custom_data, data_type, alloctype, domain_size, attribute_name_c);
}
static const void *add_generic_custom_data_layer_with_existing_data(
@@ -283,11 +275,6 @@ static const void *add_generic_custom_data_layer_with_existing_data(
void *layer_data,
const ImplicitSharingInfo *sharing_info)
{
if (attribute_id.is_anonymous()) {
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous_with_data(
&custom_data, data_type, &anonymous_id, domain_size, layer_data, sharing_info);
}
return CustomData_add_layer_named_with_data(
&custom_data, data_type, layer_data, domain_size, attribute_id.name(), sharing_info);
}
@@ -673,15 +660,15 @@ Set<AttributeIDRef> AttributeAccessor::all_ids() const
void MutableAttributeAccessor::remove_anonymous()
{
Vector<const AnonymousAttributeID *> anonymous_ids;
Vector<std::string> anonymous_ids;
for (const AttributeIDRef &id : this->all_ids()) {
if (id.is_anonymous()) {
anonymous_ids.append(&id.anonymous_id());
anonymous_ids.append(id.name());
}
}
while (!anonymous_ids.is_empty()) {
this->remove(*anonymous_ids.pop_last());
this->remove(anonymous_ids.pop_last());
}
}
@@ -835,7 +822,7 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
if (!(ATTR_DOMAIN_AS_MASK(meta_data.domain) & domain_mask)) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
if (skip.contains(id.name())) {
@@ -869,7 +856,7 @@ void gather_attributes(const AttributeAccessor src_attributes,
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
if (skip.contains(id.name())) {
@@ -911,7 +898,7 @@ void gather_attributes(const AttributeAccessor src_attributes,
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
if (skip.contains(id.name())) {
@@ -946,7 +933,7 @@ void gather_attributes_group_to_group(const AttributeAccessor src_attributes,
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
if (skip.contains(id.name())) {
@@ -979,7 +966,7 @@ void gather_attributes_to_groups(const AttributeAccessor src_attributes,
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
if (skip.contains(id.name())) {
@@ -1031,7 +1018,7 @@ void copy_attributes_group_to_group(const AttributeAccessor src_attributes,
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
if (skip.contains(id.name())) {

View File

@@ -128,9 +128,9 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
[[nodiscard]] static bool copy_bake_item_to_socket_value(
const BakeItem &bake_item,
const eNodeSocketDatatype socket_type,
const FunctionRef<std::shared_ptr<AnonymousAttributeFieldInput>(const CPPType &type)>
const FunctionRef<std::shared_ptr<AttributeFieldInput>(const CPPType &type)>
make_attribute_field,
Map<std::string, AnonymousAttributeIDPtr> &r_attribute_map,
Map<std::string, std::string> &r_attribute_map,
void *r_value)
{
switch (socket_type) {
@@ -158,12 +158,10 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
return false;
}
if (const auto *item = dynamic_cast<const AttributeBakeItem *>(&bake_item)) {
std::shared_ptr<AnonymousAttributeFieldInput> attribute_field = make_attribute_field(
base_type);
const AnonymousAttributeIDPtr &attribute_id = attribute_field->anonymous_id();
std::shared_ptr<AttributeFieldInput> attribute_field = make_attribute_field(base_type);
r_attribute_map.add(item->name(), attribute_field->attribute_name());
fn::GField field{attribute_field};
new (r_value) SocketValueVariant(std::move(field));
r_attribute_map.add(item->name(), attribute_id);
return true;
}
#ifdef WITH_OPENVDB
@@ -198,7 +196,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
}
static void rename_attributes(const Span<GeometrySet *> geometries,
const Map<std::string, AnonymousAttributeIDPtr> &attribute_map)
const Map<std::string, std::string> &attribute_map)
{
for (GeometrySet *geometry : geometries) {
for (const GeometryComponent::Type type : {GeometryComponent::Type::Mesh,
@@ -221,10 +219,8 @@ static void rename_attributes(const Span<GeometrySet *> geometries,
GeometryComponent &component = geometry->get_component_for_write(type);
MutableAttributeAccessor attributes = *component.attributes_for_write();
for (const MapItem<std::string, AnonymousAttributeIDPtr> &attribute_item :
attribute_map.items())
{
attributes.rename(attribute_item.key, *attribute_item.value);
for (const MapItem<std::string, std::string> &attribute_item : attribute_map.items()) {
attributes.rename(attribute_item.key, attribute_item.value);
}
}
}
@@ -255,11 +251,10 @@ void move_bake_items_to_socket_values(
const Span<BakeItem *> bake_items,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map,
FunctionRef<std::shared_ptr<AnonymousAttributeFieldInput>(int, const CPPType &)>
make_attribute_field,
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
const Span<void *> r_socket_values)
{
Map<std::string, AnonymousAttributeIDPtr> attribute_map;
Map<std::string, std::string> attribute_map;
Vector<GeometrySet *> geometries;
@@ -296,11 +291,10 @@ void copy_bake_items_to_socket_values(
const Span<const BakeItem *> bake_items,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map,
FunctionRef<std::shared_ptr<AnonymousAttributeFieldInput>(int, const CPPType &)>
make_attribute_field,
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
const Span<void *> r_socket_values)
{
Map<std::string, AnonymousAttributeIDPtr> attribute_map;
Map<std::string, std::string> attribute_map;
Vector<GeometrySet *> geometries;
for (const int i : bake_items.index_range()) {

View File

@@ -376,7 +376,7 @@ static bool should_add_attribute_to_mesh(const AttributeAccessor &curve_attribut
if (curve_attributes.is_builtin(id) && !mesh_attributes.is_builtin(id)) {
return false;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return false;
}
if (meta_data.data_type == CD_PROP_STRING) {

View File

@@ -2487,11 +2487,6 @@ static bool customdata_merge_internal(const CustomData *source,
new_layer->active_clone = last_clone;
new_layer->active_mask = last_mask;
changed = true;
if (src_layer.anonymous_id != nullptr) {
new_layer->anonymous_id = src_layer.anonymous_id;
new_layer->anonymous_id->add_user();
}
}
CustomData_update_typemap(dest);
@@ -2718,10 +2713,6 @@ void CustomData_init_layout_from(const CustomData *source,
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
{
if (layer->anonymous_id != nullptr) {
layer->anonymous_id->remove_user_and_delete_if_last();
layer->anonymous_id = nullptr;
}
const eCustomDataType type = eCustomDataType(layer->type);
if (layer->sharing_info == nullptr) {
if (layer->data) {
@@ -3081,7 +3072,7 @@ bool CustomData_layer_is_anonymous(const CustomData *data, eCustomDataType type,
BLI_assert(layer_index >= 0);
return data->layers[layer_index].anonymous_id != nullptr;
return blender::bke::attribute_name_is_anonymous(data->layers[layer_index].name);
}
static void customData_resize(CustomData *data, const int grow_amount)
@@ -3283,47 +3274,6 @@ const void *CustomData_add_layer_named_with_data(CustomData *data,
return nullptr;
}
void *CustomData_add_layer_anonymous(CustomData *data,
const eCustomDataType type,
const eCDAllocType alloctype,
const int totelem,
const AnonymousAttributeIDHandle *anonymous_id)
{
const StringRef name = anonymous_id->name().c_str();
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, nullptr, nullptr, totelem, name);
CustomData_update_typemap(data);
if (layer == nullptr) {
return nullptr;
}
anonymous_id->add_user();
layer->anonymous_id = anonymous_id;
return layer->data;
}
const void *CustomData_add_layer_anonymous_with_data(
CustomData *data,
const eCustomDataType type,
const AnonymousAttributeIDHandle *anonymous_id,
const int totelem,
void *layer_data,
const ImplicitSharingInfo *sharing_info)
{
const StringRef name = anonymous_id->name().c_str();
CustomDataLayer *layer = customData_add_layer__internal(
data, type, std::nullopt, layer_data, sharing_info, totelem, name);
CustomData_update_typemap(data);
if (layer == nullptr) {
return nullptr;
}
anonymous_id->add_user();
layer->anonymous_id = anonymous_id;
return layer->data;
}
bool CustomData_free_layer(CustomData *data,
const eCustomDataType type,
const int totelem,
@@ -3438,7 +3388,9 @@ int CustomData_number_of_anonymous_layers(const CustomData *data, const eCustomD
int number = 0;
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type && data->layers[i].anonymous_id != nullptr) {
if (data->layers[i].type == type &&
blender::bke::attribute_name_is_anonymous(data->layers[i].name))
{
number++;
}
}
@@ -4475,7 +4427,7 @@ void CustomData_blend_write_prepare(CustomData &data,
if (layer.flag & CD_FLAG_NOCOPY) {
continue;
}
if (layer.anonymous_id != nullptr) {
if (blender::bke::attribute_name_is_anonymous(layer.name)) {
continue;
}
if (skip_names.contains(layer.name)) {

View File

@@ -430,6 +430,9 @@ GVArray AttributeExistsFieldInput::get_varray_for_context(const bke::GeometryFie
std::string AttributeFieldInput::socket_inspection_name() const
{
if (socket_inspection_name_) {
return *socket_inspection_name_;
}
return fmt::format(TIP_("\"{}\" attribute from geometry"), name_);
}
@@ -503,47 +506,6 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
}
GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryFieldContext &context,
const IndexMask & /*mask*/) const
{
const eCustomDataType data_type = cpp_type_to_custom_data_type(*type_);
return *context.attributes()->lookup(*anonymous_id_, context.domain(), data_type);
}
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
{
return fmt::format(TIP_("\"{}\" from {}"), TIP_(debug_name_.c_str()), producer_name_);
}
uint64_t AnonymousAttributeFieldInput::hash() const
{
return get_default_hash(anonymous_id_.get(), type_);
}
bool AnonymousAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
{
if (const AnonymousAttributeFieldInput *other_typed =
dynamic_cast<const AnonymousAttributeFieldInput *>(&other))
{
return anonymous_id_.get() == other_typed->anonymous_id_.get() && type_ == other_typed->type_;
}
return false;
}
std::optional<AttrDomain> AnonymousAttributeFieldInput::preferred_domain(
const GeometryComponent &component) const
{
const std::optional<AttributeAccessor> attributes = component.attributes();
if (!attributes.has_value()) {
return std::nullopt;
}
const std::optional<AttributeMetaData> meta_data = attributes->lookup_meta_data(*anonymous_id_);
if (!meta_data.has_value()) {
return std::nullopt;
}
return meta_data->domain;
}
GVArray NamedLayerSelectionFieldInput::get_varray_for_context(
const bke::GeometryFieldContext &context, const IndexMask &mask) const
{
@@ -764,9 +726,6 @@ static std::optional<AttributeIDRef> try_get_field_direct_attribute_id(const fn:
if (const auto *field = dynamic_cast<const AttributeFieldInput *>(&any_field.node())) {
return field->attribute_name();
}
if (const auto *field = dynamic_cast<const AnonymousAttributeFieldInput *>(&any_field.node())) {
return *field->anonymous_id();
}
return {};
}

View File

@@ -635,7 +635,7 @@ void GeometrySet::propagate_attributes_from_layer_to_instances(
const AnonymousAttributePropagationInfo &propagation_info)
{
src_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
const GAttributeReader src = src_attributes.lookup(id, AttrDomain::Layer);
@@ -683,8 +683,7 @@ void GeometrySet::gather_attributes_for_propagation(
/* Propagating string attributes is not supported yet. */
return;
}
if (attribute_id.is_anonymous() &&
!propagation_info.propagate(attribute_id.anonymous_id())) {
if (attribute_id.is_anonymous() && !propagation_info.propagate(attribute_id.name())) {
return;
}

View File

@@ -49,6 +49,7 @@ set(LIB
PRIVATE bf::blenlib
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::clog
PRIVATE bf::intern::guardedalloc
)

View File

@@ -39,6 +39,7 @@ set(LIB
PRIVATE bf::depsgraph
PRIVATE bf::dna
PRIVATE bf::extern::curve_fit_nd
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::clog
PRIVATE bf::intern::guardedalloc
)

View File

@@ -35,6 +35,7 @@ set(LIB
PRIVATE bf::depsgraph
PRIVATE bf::dna
bf_editor_object
PRIVATE bf::extern::fmtlib
PRIVATE bf::intern::guardedalloc
bf_windowmanager
)

View File

@@ -305,7 +305,7 @@ blender::bke::CurvesGeometry curves_merge_by_distance(
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
src_attributes.for_all([&](const bke::AttributeIDRef &id,
const bke::AttributeMetaData &meta_data) {
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
if (meta_data.domain != bke::AttrDomain::Point) {

View File

@@ -15,8 +15,11 @@ class AttributeIDRef;
namespace blender::geometry {
Mesh *create_cuboid_mesh(
const float3 &size, int verts_x, int verts_y, int verts_z, const bke::AttributeIDRef &uv_id);
Mesh *create_cuboid_mesh(const float3 &size,
int verts_x,
int verts_y,
int verts_z,
const std::optional<std::string> &uv_id);
Mesh *create_cuboid_mesh(const float3 &size, int verts_x, int verts_y, int verts_z);

View File

@@ -11,10 +11,10 @@ struct Mesh;
namespace blender::geometry {
struct ConeAttributeOutputs {
bke::AnonymousAttributeIDPtr top_id;
bke::AnonymousAttributeIDPtr bottom_id;
bke::AnonymousAttributeIDPtr side_id;
bke::AnonymousAttributeIDPtr uv_map_id;
std::optional<std::string> top_id;
std::optional<std::string> bottom_id;
std::optional<std::string> side_id;
std::optional<std::string> uv_map_id;
};
enum class ConeFillType {

View File

@@ -11,7 +11,10 @@ class AttributeIDRef;
namespace blender::geometry {
Mesh *create_grid_mesh(
int verts_x, int verts_y, float size_x, float size_y, const bke::AttributeIDRef &uv_map_id);
Mesh *create_grid_mesh(int verts_x,
int verts_y,
float size_x,
float size_y,
const std::optional<std::string> &uv_map_id);
} // namespace blender::geometry

View File

@@ -26,6 +26,6 @@ Bounds<float3> calculate_bounds_radial_primitive(float radius_top,
Mesh *create_uv_sphere_mesh(float radius,
int segments,
int rings,
const bke::AttributeIDRef &uv_map_id);
const std::optional<std::string> &uv_map_id);
} // namespace blender::geometry

View File

@@ -14,8 +14,8 @@ namespace blender::geometry {
using bke::CurvesGeometry;
struct ResampleCurvesOutputAttributeIDs {
bke::AttributeIDRef tangent_id;
bke::AttributeIDRef normal_id;
std::optional<std::string> tangent_id;
std::optional<std::string> normal_id;
};
/**

View File

@@ -289,7 +289,7 @@ static void calculate_corner_verts(const CuboidConfig &config, MutableSpan<int>
}
}
static void calculate_uvs(const CuboidConfig &config, Mesh *mesh, const bke::AttributeIDRef &uv_id)
static void calculate_uvs(const CuboidConfig &config, Mesh *mesh, const std::string &uv_id)
{
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
bke::SpanAttributeWriter uv_attribute = attributes.lookup_or_add_for_write_only_span<float2>(
@@ -369,7 +369,7 @@ Mesh *create_cuboid_mesh(const float3 &size,
const int verts_x,
const int verts_y,
const int verts_z,
const bke::AttributeIDRef &uv_id)
const std::optional<std::string> &uv_id)
{
const CuboidConfig config(size, verts_x, verts_y, verts_z);
@@ -384,7 +384,7 @@ Mesh *create_cuboid_mesh(const float3 &size,
bke::mesh_calc_edges(*mesh, false, false);
if (uv_id) {
calculate_uvs(config, mesh, uv_id);
calculate_uvs(config, mesh, *uv_id);
}
const float3 bounds = size * 0.5f;

View File

@@ -473,7 +473,7 @@ static void calculate_selection_outputs(const ConeConfig &config,
if (attribute_outputs.top_id) {
const bool face = !config.top_is_point && config.fill_type != ConeFillType::None;
bke::SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
attribute_outputs.top_id.get(), face ? bke::AttrDomain::Face : bke::AttrDomain::Point);
*attribute_outputs.top_id, face ? bke::AttrDomain::Face : bke::AttrDomain::Point);
if (config.top_is_point) {
selection.span[config.first_vert] = true;
@@ -488,7 +488,7 @@ static void calculate_selection_outputs(const ConeConfig &config,
if (attribute_outputs.bottom_id) {
const bool face = !config.bottom_is_point && config.fill_type != ConeFillType::None;
bke::SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
attribute_outputs.bottom_id.get(), face ? bke::AttrDomain::Face : bke::AttrDomain::Point);
*attribute_outputs.bottom_id, face ? bke::AttrDomain::Face : bke::AttrDomain::Point);
if (config.bottom_is_point) {
selection.span[config.last_vert] = true;
@@ -505,7 +505,7 @@ static void calculate_selection_outputs(const ConeConfig &config,
/* Populate "Side" selection output. */
if (attribute_outputs.side_id) {
bke::SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
attribute_outputs.side_id.get(), bke::AttrDomain::Face);
*attribute_outputs.side_id, bke::AttrDomain::Face);
selection.span.slice(config.side_faces_start, config.side_faces_len).fill(true);
selection.finish();
@@ -693,7 +693,7 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
calculate_cone_faces(config, corner_verts, corner_edges, face_offsets.drop_back(1));
offset_indices::accumulate_counts_to_offsets(face_offsets);
if (attribute_outputs.uv_map_id) {
calculate_cone_uvs(config, mesh, attribute_outputs.uv_map_id.get());
calculate_cone_uvs(config, mesh, *attribute_outputs.uv_map_id);
}
calculate_selection_outputs(config, attribute_outputs, mesh->attributes_for_write());

View File

@@ -41,7 +41,7 @@ Mesh *create_grid_mesh(const int verts_x,
const int verts_y,
const float size_x,
const float size_y,
const bke::AttributeIDRef &uv_map_id)
const std::optional<std::string> &uv_map_id)
{
BLI_assert(verts_x > 0 && verts_y > 0);
const int edges_x = verts_x - 1;
@@ -143,7 +143,7 @@ Mesh *create_grid_mesh(const int verts_x,
});
if (uv_map_id && mesh->faces_num != 0) {
calculate_uvs(mesh, positions, corner_verts, size_x, size_y, uv_map_id);
calculate_uvs(mesh, positions, corner_verts, size_x, size_y, *uv_map_id);
}
if (verts_x > 1 || verts_y > 1) {

View File

@@ -235,7 +235,7 @@ BLI_NOINLINE static void calculate_sphere_corners(MutableSpan<int> corner_verts,
BLI_NOINLINE static void calculate_sphere_uvs(Mesh *mesh,
const float segments,
const float rings,
const bke::AttributeIDRef &uv_map_id)
const StringRef uv_map_id)
{
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
@@ -294,7 +294,7 @@ static Bounds<float3> calculate_bounds_uv_sphere(const float radius,
Mesh *create_uv_sphere_mesh(const float radius,
const int segments,
const int rings,
const bke::AttributeIDRef &uv_map_id)
const std::optional<std::string> &uv_map_id)
{
Mesh *mesh = BKE_mesh_new_nomain(sphere_vert_total(segments, rings),
sphere_edge_total(segments, rings),
@@ -319,7 +319,7 @@ Mesh *create_uv_sphere_mesh(const float radius,
[&]() { calculate_sphere_corners(corner_verts, corner_edges, segments, rings); },
[&]() {
if (uv_map_id) {
calculate_sphere_uvs(mesh, segments, rings, uv_map_id);
calculate_sphere_uvs(mesh, segments, rings, *uv_map_id);
}
});

View File

@@ -61,7 +61,7 @@ BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
if (skip.contains(id.name())) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}

View File

@@ -123,7 +123,7 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points,
/* Transfer all other attributes. */
for (const bke::AttributeIDRef &id : attribute_ids) {
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
continue;
}

View File

@@ -869,7 +869,7 @@ static void gather_attributes_for_propagation(
return;
}
if (attribute_id.is_anonymous() &&
!propagation_info.propagate(attribute_id.anonymous_id())) {
!propagation_info.propagate(attribute_id.name())) {
return;
}

View File

@@ -225,7 +225,7 @@ static void clean_unused_attributes(const bke::AnonymousAttributePropagationInfo
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (propagation_info.propagate(id.anonymous_id())) {
if (propagation_info.propagate(id.name())) {
return true;
}
unused_ids.append(id.name());

View File

@@ -183,14 +183,14 @@ static void gather_point_attributes_to_interpolate(
if (output_ids.tangent_id) {
result.src_evaluated_tangents = src_curves.evaluated_tangents();
bke::GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
output_ids.tangent_id, bke::AttrDomain::Point, CD_PROP_FLOAT3);
*output_ids.tangent_id, bke::AttrDomain::Point, CD_PROP_FLOAT3);
result.dst_tangents = dst_attribute.span.typed<float3>();
result.dst_attributes.append(std::move(dst_attribute));
}
if (output_ids.normal_id) {
result.src_evaluated_normals = src_curves.evaluated_normals();
bke::GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
output_ids.normal_id, bke::AttrDomain::Point, CD_PROP_FLOAT3);
*output_ids.normal_id, bke::AttrDomain::Point, CD_PROP_FLOAT3);
result.dst_normals = dst_attribute.span.typed<float3>();
result.dst_attributes.append(std::move(dst_attribute));
}

View File

@@ -14,16 +14,6 @@
#include "BLI_implicit_sharing.h"
/** Workaround to forward-declare C++ type in C header. */
#ifdef __cplusplus
namespace blender::bke {
class AnonymousAttributeID;
} // namespace blender::bke
using AnonymousAttributeIDHandle = blender::bke::AnonymousAttributeID;
#else
typedef struct AnonymousAttributeIDHandle AnonymousAttributeIDHandle;
#endif
/** Descriptor and storage for a custom data layer. */
typedef struct CustomDataLayer {
/** Type of data in layer. */
@@ -47,11 +37,6 @@ typedef struct CustomDataLayer {
char _pad1[4];
/** Layer data. */
void *data;
/**
* Run-time identifier for this layer. Can be used to retrieve information about where this
* attribute was created.
*/
const AnonymousAttributeIDHandle *anonymous_id;
/**
* Run-time data that allows sharing `data` with other entities (mostly custom data layers on
* other geometries).

View File

@@ -17,7 +17,7 @@
void *data) \
{ \
CustomDataLayer *layer = (CustomDataLayer *)data; \
return (layer->anonymous_id != NULL || layer->type != layer_type); \
return (blender::bke::attribute_name_is_anonymous(layer->name) || layer->type != layer_type); \
} \
/* begin */ \
[[maybe_unused]] static void rna_Mesh_##collection_name##s_begin( \

View File

@@ -146,6 +146,7 @@ set(LIB
bf_nodes_shader
bf_nodes_texture
PRIVATE bf::extern::fmtlib
PRIVATE bf::extern::xxhash
)
if(WITH_BULLET)

View File

@@ -24,9 +24,6 @@
namespace blender::nodes {
using bke::AnonymousAttributeFieldInput;
using bke::AnonymousAttributeID;
using bke::AnonymousAttributeIDPtr;
using bke::AnonymousAttributePropagationInfo;
using bke::AttrDomain;
using bke::AttributeAccessor;
@@ -67,7 +64,7 @@ class GeoNodeExecParams {
const lf::Context &lf_context_;
const Span<int> lf_input_for_output_bsocket_usage_;
const Span<int> lf_input_for_attribute_propagation_to_output_;
const FunctionRef<AnonymousAttributeIDPtr(int)> get_output_attribute_id_;
const FunctionRef<std::string(int)> get_output_attribute_id_;
public:
GeoNodeExecParams(const bNode &node,
@@ -75,7 +72,7 @@ class GeoNodeExecParams {
const lf::Context &lf_context,
const Span<int> lf_input_for_output_bsocket_usage,
const Span<int> lf_input_for_attribute_propagation_to_output,
const FunctionRef<AnonymousAttributeIDPtr(int)> get_output_attribute_id)
const FunctionRef<std::string(int)> get_output_attribute_id)
: node_(node),
params_(params),
lf_context_(lf_context),
@@ -275,11 +272,11 @@ class GeoNodeExecParams {
* Return a new anonymous attribute id for the given output. None is returned if the anonymous
* attribute is not needed.
*/
AnonymousAttributeIDPtr get_output_anonymous_attribute_id_if_needed(
std::optional<std::string> get_output_anonymous_attribute_id_if_needed(
const StringRef output_identifier, const bool force_create = false)
{
if (!this->anonymous_attribute_output_is_required(output_identifier) && !force_create) {
return {};
return std::nullopt;
}
const bNodeSocket &output_socket = node_.output_by_identifier(output_identifier);
return get_output_attribute_id_(output_socket.index());

View File

@@ -449,6 +449,10 @@ std::unique_ptr<LazyFunction> get_warning_node_lazy_function(const bNode &node);
*/
void set_default_remaining_node_outputs(lf::Params &params, const bNode &node);
std::string make_anonymous_attribute_socket_inspection_string(const bNodeSocket &socket);
std::string make_anonymous_attribute_socket_inspection_string(StringRef node_name,
StringRef socket_name);
struct FoundNestedNodeID {
int id;
bool is_in_simulation = false;
@@ -458,23 +462,6 @@ struct FoundNestedNodeID {
std::optional<FoundNestedNodeID> find_nested_node_id(const GeoNodesLFUserData &user_data,
const int node_id);
/**
* An anonymous attribute created by a node.
*/
class NodeAnonymousAttributeID : public bke::AnonymousAttributeID {
std::string long_name_;
std::string socket_name_;
public:
NodeAnonymousAttributeID(const Object &object,
const ComputeContext &compute_context,
const bNode &bnode,
const StringRef identifier,
const StringRef name);
std::string user_name() const override;
};
/**
* Main function that converts a #bNodeTree into a lazy-function graph. If the graph has been
* generated already, nothing is done. Under some circumstances a valid graph cannot be created. In

View File

@@ -252,6 +252,7 @@ set(LIB
bf_nodes
PRIVATE bf::intern::atomic
PRIVATE bf::extern::fmtlib
PRIVATE bf::extern::xxhash
)
if(WITH_IO_STL)

View File

@@ -186,7 +186,7 @@ static void clean_unused_attributes(const AnonymousAttributePropagationInfo &pro
if (skip.contains(id)) {
return true;
}
if (propagation_info.propagate(id.anonymous_id())) {
if (propagation_info.propagate(id.name())) {
return true;
}
unused_ids.append(id.name());
@@ -215,7 +215,7 @@ static void node_geo_exec(GeoNodeExecParams params)
Vector<const NodeGeometryAttributeCaptureItem *> used_items;
Vector<GField> fields;
Vector<AnonymousAttributeIDPtr> attribute_id_ptrs;
Vector<std::string> attribute_id_ptrs;
Set<AttributeIDRef> used_attribute_ids_set;
for (const NodeGeometryAttributeCaptureItem &item :
Span{storage.capture_items, storage.capture_items_num})
@@ -224,14 +224,14 @@ static void node_geo_exec(GeoNodeExecParams params)
CaptureAttributeItemsAccessor::input_socket_identifier_for_item(item);
const std::string output_identifier =
CaptureAttributeItemsAccessor::output_socket_identifier_for_item(item);
AnonymousAttributeIDPtr attribute_id = params.get_output_anonymous_attribute_id_if_needed(
std::optional<std::string> attribute_id = params.get_output_anonymous_attribute_id_if_needed(
output_identifier);
if (!attribute_id) {
continue;
}
used_attribute_ids_set.add(*attribute_id);
fields.append(params.extract_input<GField>(input_identifier));
attribute_id_ptrs.append(std::move(attribute_id));
attribute_id_ptrs.append(std::move(*attribute_id));
used_items.append(&item);
}
@@ -243,7 +243,7 @@ static void node_geo_exec(GeoNodeExecParams params)
Array<AttributeIDRef> attribute_ids(attribute_id_ptrs.size());
for (const int i : attribute_id_ptrs.index_range()) {
attribute_ids[i] = *attribute_id_ptrs[i];
attribute_ids[i] = attribute_id_ptrs[i];
}
const auto capture_on = [&](GeometryComponent &component) {

View File

@@ -15,6 +15,7 @@
#include "BLI_string.h"
#include "BKE_anonymous_attribute_make.hh"
#include "BKE_bake_geometry_nodes_modifier.hh"
#include "BKE_bake_items_socket.hh"
#include "BKE_context.hh"
@@ -535,21 +536,17 @@ class LazyFunctionForBakeNode final : public LazyFunction {
r_output_values);
}
std::shared_ptr<AnonymousAttributeFieldInput> make_attribute_field(
const Object &self_object,
const ComputeContext &compute_context,
const NodeGeometryBakeItem &item,
const CPPType &type) const
std::shared_ptr<AttributeFieldInput> make_attribute_field(const Object &self_object,
const ComputeContext &compute_context,
const NodeGeometryBakeItem &item,
const CPPType &type) const
{
AnonymousAttributeIDPtr attribute_id = AnonymousAttributeIDPtr(
MEM_new<NodeAnonymousAttributeID>(__func__,
self_object,
compute_context,
node_,
std::to_string(item.identifier),
item.name));
return std::make_shared<AnonymousAttributeFieldInput>(
attribute_id, type, node_.label_or_name());
std::string attribute_name = bke::hash_to_anonymous_attribute_name(
compute_context.hash(), self_object.id.name, node_.identifier, item.identifier);
std::string socket_inspection_name = make_anonymous_attribute_socket_inspection_string(
node_.label_or_name(), item.name);
return std::make_shared<AttributeFieldInput>(
std::move(attribute_name), type, std::move(socket_inspection_name));
}
};

View File

@@ -42,7 +42,7 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
}
struct AttributeOutputs {
AnonymousAttributeIDPtr intersecting_edges_id;
std::optional<std::string> intersecting_edges_id;
};
static void node_update(bNodeTree *ntree, bNode *node)
@@ -198,7 +198,7 @@ static void node_geo_exec(GeoNodeExecParams params)
if (attribute_outputs.intersecting_edges_id) {
MutableAttributeAccessor attributes = result->attributes_for_write();
SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_only_span<bool>(
attribute_outputs.intersecting_edges_id.get(), AttrDomain::Edge);
*attribute_outputs.intersecting_edges_id, AttrDomain::Edge);
selection.span.fill(false);
for (const int i : intersecting_edges) {

View File

@@ -60,11 +60,10 @@ static Curves *create_star_curve(const float inner_radius,
return curves_id;
}
static void create_selection_output(CurveComponent &component,
AnonymousAttributeIDPtr &r_attribute)
static void create_selection_output(CurveComponent &component, const StringRef &r_attribute)
{
SpanAttributeWriter<bool> selection =
component.attributes_for_write()->lookup_or_add_for_write_only_span<bool>(*r_attribute,
component.attributes_for_write()->lookup_or_add_for_write_only_span<bool>(r_attribute,
AttrDomain::Point);
for (int i : selection.span.index_range()) {
selection.span[i] = i % 2 == 0;
@@ -80,10 +79,10 @@ static void node_geo_exec(GeoNodeExecParams params)
std::max(params.extract_input<int>("Points"), 3));
GeometrySet output = GeometrySet::from_curves(curves);
if (AnonymousAttributeIDPtr outer_points_id = params.get_output_anonymous_attribute_id_if_needed(
"Outer Points"))
if (std::optional<std::string> outer_points_id =
params.get_output_anonymous_attribute_id_if_needed("Outer Points"))
{
create_selection_output(output.get_component_for_write<CurveComponent>(), outer_points_id);
create_selection_output(output.get_component_for_write<CurveComponent>(), *outer_points_id);
}
params.set_output("Curve", std::move(output));
}

View File

@@ -110,19 +110,19 @@ static void copy_curve_domain_attributes(const AttributeAccessor curve_attribute
}
static PointCloud *pointcloud_from_curves(bke::CurvesGeometry curves,
const AttributeIDRef &tangent_id,
const AttributeIDRef &normal_id,
const AttributeIDRef &rotation_id)
const std::optional<std::string> &tangent_id,
const std::optional<std::string> &normal_id,
const std::optional<std::string> &rotation_id)
{
PointCloud *pointcloud = BKE_pointcloud_new_nomain(0);
pointcloud->totpoint = curves.points_num();
if (rotation_id) {
MutableAttributeAccessor attributes = curves.attributes_for_write();
const VArraySpan tangents = *attributes.lookup<float3>(tangent_id, AttrDomain::Point);
const VArraySpan normals = *attributes.lookup<float3>(normal_id, AttrDomain::Point);
const VArraySpan tangents = *attributes.lookup<float3>(*tangent_id, AttrDomain::Point);
const VArraySpan normals = *attributes.lookup<float3>(*normal_id, AttrDomain::Point);
SpanAttributeWriter<math::Quaternion> rotations =
attributes.lookup_or_add_for_write_only_span<math::Quaternion>(rotation_id,
attributes.lookup_or_add_for_write_only_span<math::Quaternion>(*rotation_id,
AttrDomain::Point);
fill_rotation_attribute(tangents, normals, rotations.span);
rotations.finish();
@@ -142,7 +142,7 @@ static void curve_to_points(GeometrySet &geometry_set,
GeoNodeExecParams params,
const GeometryNodeCurveResampleMode mode,
geometry::ResampleCurvesOutputAttributeIDs resample_attributes,
AnonymousAttributeIDPtr rotation_anonymous_id)
std::optional<std::string> rotation_anonymous_id)
{
switch (mode) {
case GEO_NODE_CURVE_RESAMPLE_COUNT: {
@@ -160,7 +160,7 @@ static void curve_to_points(GeometrySet &geometry_set,
PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves),
resample_attributes.tangent_id,
resample_attributes.normal_id,
rotation_anonymous_id.get());
rotation_anonymous_id);
geometry.remove_geometry_during_modify();
geometry.replace_pointcloud(pointcloud);
}
@@ -182,7 +182,7 @@ static void curve_to_points(GeometrySet &geometry_set,
PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves),
resample_attributes.tangent_id,
resample_attributes.normal_id,
rotation_anonymous_id.get());
rotation_anonymous_id);
geometry.remove_geometry_during_modify();
geometry.replace_pointcloud(pointcloud);
}
@@ -199,7 +199,7 @@ static void curve_to_points(GeometrySet &geometry_set,
PointCloud *pointcloud = pointcloud_from_curves(std::move(dst_curves),
resample_attributes.tangent_id,
resample_attributes.normal_id,
rotation_anonymous_id.get());
rotation_anonymous_id);
geometry.remove_geometry_during_modify();
geometry.replace_pointcloud(pointcloud);
}
@@ -213,7 +213,7 @@ static void grease_pencil_to_points(GeometrySet &geometry_set,
GeoNodeExecParams params,
const GeometryNodeCurveResampleMode mode,
geometry::ResampleCurvesOutputAttributeIDs resample_attributes,
AnonymousAttributeIDPtr rotation_anonymous_id,
std::optional<std::string> rotation_anonymous_id,
const AnonymousAttributePropagationInfo &propagation_info)
{
Field<int> count;
@@ -273,7 +273,7 @@ static void grease_pencil_to_points(GeometrySet &geometry_set,
pointcloud_by_layer[layer_index] = pointcloud_from_curves(std::move(dst_curves),
resample_attributes.tangent_id,
resample_attributes.normal_id,
rotation_anonymous_id.get());
rotation_anonymous_id);
}
if (!pointcloud_by_layer.is_empty()) {
InstancesComponent &instances_component =
@@ -314,17 +314,17 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometryComponentEditData::remember_deformed_positions_if_necessary(geometry_set);
AnonymousAttributeIDPtr rotation_anonymous_id =
std::optional<std::string> rotation_anonymous_id =
params.get_output_anonymous_attribute_id_if_needed("Rotation");
const bool need_tangent_and_normal = bool(rotation_anonymous_id);
AnonymousAttributeIDPtr tangent_anonymous_id =
std::optional<std::string> tangent_anonymous_id =
params.get_output_anonymous_attribute_id_if_needed("Tangent", need_tangent_and_normal);
AnonymousAttributeIDPtr normal_anonymous_id = params.get_output_anonymous_attribute_id_if_needed(
"Normal", need_tangent_and_normal);
std::optional<std::string> normal_anonymous_id =
params.get_output_anonymous_attribute_id_if_needed("Normal", need_tangent_and_normal);
geometry::ResampleCurvesOutputAttributeIDs resample_attributes;
resample_attributes.tangent_id = tangent_anonymous_id.get();
resample_attributes.normal_id = normal_anonymous_id.get();
resample_attributes.tangent_id = tangent_anonymous_id;
resample_attributes.normal_id = normal_anonymous_id;
const AnonymousAttributePropagationInfo &propagation_info = params.get_output_propagation_info(
"Points");

View File

@@ -139,7 +139,7 @@ static GreasePencil *curve_instances_to_grease_pencil_layers(
if (ELEM(attribute_id, "opacity")) {
return true;
}
if (attribute_id.is_anonymous() && !propagation_info.propagate(attribute_id.anonymous_id())) {
if (attribute_id.is_anonymous() && !propagation_info.propagate(attribute_id.name())) {
return true;
}
const GAttributeReader src_attribute = instances_attributes.lookup(attribute_id);

View File

@@ -318,8 +318,8 @@ BLI_NOINLINE static void propagate_existing_attributes(
namespace {
struct AttributeOutputs {
AnonymousAttributeIDPtr normal_id;
AnonymousAttributeIDPtr rotation_id;
std::optional<std::string> normal_id;
std::optional<std::string> rotation_id;
};
} // namespace
@@ -413,11 +413,11 @@ BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh,
if (attribute_outputs.normal_id) {
normals = point_attributes.lookup_or_add_for_write_only_span<float3>(
attribute_outputs.normal_id.get(), AttrDomain::Point);
*attribute_outputs.normal_id, AttrDomain::Point);
}
if (attribute_outputs.rotation_id) {
rotations = point_attributes.lookup_or_add_for_write_only_span<math::Quaternion>(
attribute_outputs.rotation_id.get(), AttrDomain::Point);
*attribute_outputs.rotation_id, AttrDomain::Point);
}
threading::parallel_for(bary_coords.index_range(), 1024, [&](const IndexRange range) {

View File

@@ -146,7 +146,7 @@ static void transfer_attributes(
attribute_ids.remove(".corner_edge");
attribute_ids.remove("sharp_face");
attribute_ids.remove_if([&](const AttributeIDRef &id) {
return id.is_anonymous() && !propagation_info.propagate(id.anonymous_id());
return id.is_anonymous() && !propagation_info.propagate(id.name());
});
for (const AttributeIDRef &id : attribute_ids) {

View File

@@ -56,7 +56,7 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
}
struct IndexAttributes {
AnonymousAttributeIDPtr duplicate_index;
std::optional<std::string> duplicate_index;
};
/* -------------------------------------------------------------------- */
@@ -112,7 +112,7 @@ static void create_duplicate_index_attribute(bke::MutableAttributeAccessor attri
const OffsetIndices<int> offsets)
{
SpanAttributeWriter<int> duplicate_indices = attributes.lookup_or_add_for_write_only_span<int>(
attribute_outputs.duplicate_index.get(), output_domain);
*attribute_outputs.duplicate_index, output_domain);
for (const int i : IndexRange(selection.size())) {
MutableSpan<int> indices = duplicate_indices.span.slice(offsets[i]);
for (const int i : indices.index_range()) {

View File

@@ -72,12 +72,12 @@ static void node_update(bNodeTree *ntree, bNode *node)
}
struct AttributeOutputs {
AnonymousAttributeIDPtr top_id;
AnonymousAttributeIDPtr side_id;
std::optional<std::string> top_id;
std::optional<std::string> side_id;
};
static void save_selection_as_attribute(MutableAttributeAccessor attributes,
const AnonymousAttributeID *id,
const StringRef id,
const AttrDomain domain,
const IndexMask &selection)
{
@@ -99,7 +99,7 @@ static void remove_non_propagated_attributes(
if (!id.is_anonymous()) {
return true;
}
if (propagation_info.propagate(id.anonymous_id())) {
if (propagation_info.propagate(id.name())) {
return true;
}
return false;
@@ -454,11 +454,11 @@ static void extrude_mesh_vertices(Mesh &mesh,
if (attribute_outputs.top_id) {
save_selection_as_attribute(
attributes, attribute_outputs.top_id.get(), AttrDomain::Point, new_vert_range);
attributes, *attribute_outputs.top_id, AttrDomain::Point, new_vert_range);
}
if (attribute_outputs.side_id) {
save_selection_as_attribute(
attributes, attribute_outputs.side_id.get(), AttrDomain::Edge, new_edge_range);
attributes, *attribute_outputs.side_id, AttrDomain::Edge, new_edge_range);
}
const bool no_loose_vert_hint = mesh.runtime->loose_verts_cache.is_cached() &&
@@ -813,11 +813,11 @@ static void extrude_mesh_edges(Mesh &mesh,
if (attribute_outputs.top_id) {
save_selection_as_attribute(
attributes, attribute_outputs.top_id.get(), AttrDomain::Edge, duplicate_edge_range);
attributes, *attribute_outputs.top_id, AttrDomain::Edge, duplicate_edge_range);
}
if (attribute_outputs.side_id) {
save_selection_as_attribute(
attributes, attribute_outputs.side_id.get(), AttrDomain::Face, new_face_range);
attributes, *attribute_outputs.side_id, AttrDomain::Face, new_face_range);
}
tag_mesh_added_faces(mesh);
@@ -1209,11 +1209,11 @@ static void extrude_mesh_face_regions(Mesh &mesh,
if (attribute_outputs.top_id) {
save_selection_as_attribute(
attributes, attribute_outputs.top_id.get(), AttrDomain::Face, face_selection);
attributes, *attribute_outputs.top_id, AttrDomain::Face, face_selection);
}
if (attribute_outputs.side_id) {
save_selection_as_attribute(
attributes, attribute_outputs.side_id.get(), AttrDomain::Face, side_face_range);
attributes, *attribute_outputs.side_id, AttrDomain::Face, side_face_range);
}
tag_mesh_added_faces(mesh);
@@ -1457,11 +1457,11 @@ static void extrude_individual_mesh_faces(
if (attribute_outputs.top_id) {
save_selection_as_attribute(
attributes, attribute_outputs.top_id.get(), AttrDomain::Face, face_selection);
attributes, *attribute_outputs.top_id, AttrDomain::Face, face_selection);
}
if (attribute_outputs.side_id) {
save_selection_as_attribute(
attributes, attribute_outputs.side_id.get(), AttrDomain::Face, side_face_range);
attributes, *attribute_outputs.side_id, AttrDomain::Face, side_face_range);
}
tag_mesh_added_faces(mesh);

View File

@@ -463,7 +463,7 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves,
* that they had on the guides. */
guide_curve_attributes.for_all([&](const AttributeIDRef &id,
const AttributeMetaData &meta_data) {
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
const eCustomDataType type = meta_data.data_type;
@@ -602,7 +602,7 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves,
if (guide_curve_attributes.contains(id)) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
if (id.is_anonymous() && !propagation_info.propagate(id.name())) {
return true;
}
if (meta_data.data_type == CD_PROP_STRING) {
@@ -624,8 +624,8 @@ static void interpolate_curve_attributes(bke::CurvesGeometry &child_curves,
}
static void store_output_attributes(bke::CurvesGeometry &child_curves,
const AnonymousAttributeIDPtr weight_attribute_id,
const AnonymousAttributeIDPtr index_attribute_id,
const std::optional<std::string> weight_attribute_id,
const std::optional<std::string> index_attribute_id,
const int max_neighbors,
const Span<int> all_neighbor_counts,
const Span<int> all_neighbor_indices,
@@ -689,8 +689,8 @@ static GeometrySet generate_interpolated_curves(
const VArray<int> &point_group_ids,
const int max_neighbors,
const AnonymousAttributePropagationInfo &propagation_info,
const AnonymousAttributeIDPtr &index_attribute_id,
const AnonymousAttributeIDPtr &weight_attribute_id)
const std::optional<std::string> &index_attribute_id,
const std::optional<std::string> &weight_attribute_id)
{
const bke::CurvesGeometry &guide_curves = guide_curves_id.geometry.wrap();
@@ -847,10 +847,10 @@ static void node_geo_exec(GeoNodeExecParams params)
const AnonymousAttributePropagationInfo propagation_info = params.get_output_propagation_info(
"Curves");
AnonymousAttributeIDPtr index_attribute_id = params.get_output_anonymous_attribute_id_if_needed(
"Closest Index");
AnonymousAttributeIDPtr weight_attribute_id = params.get_output_anonymous_attribute_id_if_needed(
"Closest Weight");
std::optional<std::string> index_attribute_id =
params.get_output_anonymous_attribute_id_if_needed("Closest Index");
std::optional<std::string> weight_attribute_id =
params.get_output_anonymous_attribute_id_if_needed("Closest Weight");
GeometrySet new_curves = generate_interpolated_curves(guide_curves_id,
*points_component->attributes(),

View File

@@ -46,7 +46,7 @@ static Mesh *create_cube_mesh(const float3 size,
const int verts_x,
const int verts_y,
const int verts_z,
const AttributeIDRef &uv_map_id)
const std::optional<std::string> &uv_map_id)
{
const int dimensions = (verts_x - 1 > 0) + (verts_y - 1 > 0) + (verts_z - 1 > 0);
if (dimensions == 0) {
@@ -102,9 +102,10 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
AnonymousAttributeIDPtr uv_map_id = params.get_output_anonymous_attribute_id_if_needed("UV Map");
std::optional<std::string> uv_map_id = params.get_output_anonymous_attribute_id_if_needed(
"UV Map");
Mesh *mesh = create_cube_mesh(size, verts_x, verts_y, verts_z, uv_map_id.get());
Mesh *mesh = create_cube_mesh(size, verts_x, verts_y, verts_z, uv_map_id);
BKE_id_material_eval_ensure_default_slot(&mesh->id);
params.set_output("Mesh", GeometrySet::from_mesh(mesh));

View File

@@ -47,9 +47,10 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
AnonymousAttributeIDPtr uv_map_id = params.get_output_anonymous_attribute_id_if_needed("UV Map");
std::optional<std::string> uv_map_id = params.get_output_anonymous_attribute_id_if_needed(
"UV Map");
Mesh *mesh = geometry::create_grid_mesh(verts_x, verts_y, size_x, size_y, uv_map_id.get());
Mesh *mesh = geometry::create_grid_mesh(verts_x, verts_y, size_x, size_y, uv_map_id);
BKE_id_material_eval_ensure_default_slot(reinterpret_cast<ID *>(mesh));
params.set_output("Mesh", GeometrySet::from_mesh(mesh));

View File

@@ -62,7 +62,7 @@ static Bounds<float3> calculate_bounds_ico_sphere(const float radius, const int
static Mesh *create_ico_sphere_mesh(const int subdivisions,
const float radius,
const AttributeIDRef &uv_map_id)
const std::optional<std::string> &uv_map_id)
{
if (subdivisions >= 3) {
/* Most nodes don't need this because they internally use multi-threading which triggers
@@ -105,7 +105,7 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions,
if (create_uv_map) {
const VArraySpan orig_uv_map = *attributes.lookup<float2>("UVMap");
SpanAttributeWriter<float2> uv_map = attributes.lookup_or_add_for_write_only_span<float2>(
uv_map_id, AttrDomain::Corner);
*uv_map_id, AttrDomain::Corner);
uv_map.span.copy_from(orig_uv_map);
uv_map.finish();
}
@@ -123,9 +123,10 @@ static void node_geo_exec(GeoNodeExecParams params)
const int subdivisions = std::min(params.extract_input<int>("Subdivisions"), 10);
const float radius = params.extract_input<float>("Radius");
AnonymousAttributeIDPtr uv_map_id = params.get_output_anonymous_attribute_id_if_needed("UV Map");
std::optional<std::string> uv_map_id = params.get_output_anonymous_attribute_id_if_needed(
"UV Map");
Mesh *mesh = create_ico_sphere_mesh(subdivisions, radius, uv_map_id.get());
Mesh *mesh = create_ico_sphere_mesh(subdivisions, radius, uv_map_id);
params.set_output("Mesh", GeometrySet::from_mesh(mesh));
}

View File

@@ -45,9 +45,10 @@ static void node_geo_exec(GeoNodeExecParams params)
const float radius = params.extract_input<float>("Radius");
AnonymousAttributeIDPtr uv_map_id = params.get_output_anonymous_attribute_id_if_needed("UV Map");
std::optional<std::string> uv_map_id = params.get_output_anonymous_attribute_id_if_needed(
"UV Map");
Mesh *mesh = geometry::create_uv_sphere_mesh(radius, segments_num, rings_num, uv_map_id.get());
Mesh *mesh = geometry::create_uv_sphere_mesh(radius, segments_num, rings_num, uv_map_id);
BKE_id_material_eval_ensure_default_slot(reinterpret_cast<ID *>(mesh));
params.set_output("Mesh", GeometrySet::from_mesh(mesh));
}

View File

@@ -8,6 +8,7 @@
#include "BLI_string_utils.hh"
#include "BLI_task.hh"
#include "BKE_anonymous_attribute_make.hh"
#include "BKE_attribute_math.hh"
#include "BKE_bake_geometry_nodes_modifier.hh"
#include "BKE_bake_items_socket.hh"
@@ -101,16 +102,19 @@ static bke::bake::BakeSocketConfig make_bake_socket_config(
return config;
}
static std::shared_ptr<AnonymousAttributeFieldInput> make_attribute_field(
static std::shared_ptr<AttributeFieldInput> make_attribute_field(
const Object &self_object,
const ComputeContext &compute_context,
const bNode &node,
const NodeSimulationItem &item,
const CPPType &type)
{
AnonymousAttributeIDPtr attribute_id = AnonymousAttributeIDPtr(MEM_new<NodeAnonymousAttributeID>(
__func__, self_object, compute_context, node, std::to_string(item.identifier), item.name));
return std::make_shared<AnonymousAttributeFieldInput>(attribute_id, type, node.label_or_name());
std::string attribute_name = bke::hash_to_anonymous_attribute_name(
self_object.id.name, compute_context.hash(), node.identifier, item.identifier);
std::string socket_inspection_name = make_anonymous_attribute_socket_inspection_string(
node.label_or_name(), item.name);
return std::make_shared<AttributeFieldInput>(
std::move(attribute_name), type, std::move(socket_inspection_name));
}
static void move_simulation_state_to_values(const Span<NodeSimulationItem> node_simulation_items,

View File

@@ -310,7 +310,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const int total_groups_num = geometry_by_group_id.size();
dst_instances->resize(total_groups_num);
AnonymousAttributeIDPtr dst_group_id_attribute_id =
std::optional<std::string> dst_group_id_attribute_id =
params.get_output_anonymous_attribute_id_if_needed("Group ID");
if (dst_group_id_attribute_id) {
SpanAttributeWriter<int> dst_group_id =

View File

@@ -335,7 +335,8 @@ static void create_attributes(GeoNodeExecParams &params,
{
MutableAttributeAccessor attributes = instances.attributes_for_write();
if (AnonymousAttributeIDPtr line_id = params.get_output_anonymous_attribute_id_if_needed("Line"))
if (std::optional<std::string> line_id = params.get_output_anonymous_attribute_id_if_needed(
"Line"))
{
SpanAttributeWriter<int> line_attribute = attributes.lookup_or_add_for_write_only_span<int>(
*line_id, AttrDomain::Instance);
@@ -343,7 +344,7 @@ static void create_attributes(GeoNodeExecParams &params,
line_attribute.finish();
}
if (AnonymousAttributeIDPtr pivot_id = params.get_output_anonymous_attribute_id_if_needed(
if (std::optional<std::string> pivot_id = params.get_output_anonymous_attribute_id_if_needed(
"Pivot Point"))
{
SpanAttributeWriter<float3> pivot_attribute =

View File

@@ -37,6 +37,7 @@
#include "DNA_ID.h"
#include "BKE_anonymous_attribute_make.hh"
#include "BKE_compute_contexts.hh"
#include "BKE_geometry_nodes_gizmos_transforms.hh"
#include "BKE_geometry_set.hh"
@@ -122,34 +123,6 @@ static void lazy_function_interface_from_node(const bNode &node,
}
}
NodeAnonymousAttributeID::NodeAnonymousAttributeID(const Object &object,
const ComputeContext &compute_context,
const bNode &bnode,
const StringRef identifier,
const StringRef name)
: socket_name_(name)
{
const ComputeContextHash &hash = compute_context.hash();
{
std::stringstream ss;
ss << hash << "_" << object.id.name << "_" << bnode.identifier << "_" << identifier;
long_name_ = ss.str();
}
{
uint64_t hash_result[2];
BLI_hash_md5_buffer(long_name_.data(), long_name_.size(), hash_result);
std::stringstream ss;
ss << ".a_" << std::hex << hash_result[0] << hash_result[1];
name_ = ss.str();
BLI_assert(name_.size() < MAX_CUSTOMDATA_LAYER_NAME);
}
}
std::string NodeAnonymousAttributeID::user_name() const
{
return socket_name_;
}
/**
* Used for most normal geometry nodes like Subdivision Surface and Set Position.
*/
@@ -164,15 +137,6 @@ class LazyFunctionForGeometryNode : public LazyFunction {
*/
Vector<bool> is_attribute_output_bsocket_;
struct OutputAttributeID {
int bsocket_index;
AnonymousAttributeIDPtr attribute_id;
};
struct Storage {
Vector<OutputAttributeID, 1> attributes;
};
public:
LazyFunctionForGeometryNode(const bNode &node,
GeometryNodesLazyFunctionGraphInfo &own_lf_graph_info)
@@ -225,43 +189,12 @@ class LazyFunctionForGeometryNode : public LazyFunction {
}
}
void *init_storage(LinearAllocator<> &allocator) const override
{
return allocator.construct<Storage>().release();
}
void destruct_storage(void *storage) const override
{
Storage *s = static_cast<Storage *>(storage);
std::destroy_at(s);
}
void execute_impl(lf::Params &params, const lf::Context &context) const override
{
Storage *storage = static_cast<Storage *>(context.storage);
GeoNodesLFUserData *user_data = dynamic_cast<GeoNodesLFUserData *>(context.user_data);
BLI_assert(user_data != nullptr);
const auto &local_user_data = *static_cast<GeoNodesLFLocalUserData *>(context.local_user_data);
/* Lazily create the required anonymous attribute ids. */
auto get_output_attribute_id = [&](const int output_bsocket_index) -> AnonymousAttributeIDPtr {
for (const OutputAttributeID &node_output_attribute : storage->attributes) {
if (node_output_attribute.bsocket_index == output_bsocket_index) {
return node_output_attribute.attribute_id;
}
}
const bNodeSocket &bsocket = node_.output_socket(output_bsocket_index);
AnonymousAttributeIDPtr attribute_id = AnonymousAttributeIDPtr(
MEM_new<NodeAnonymousAttributeID>(__func__,
*user_data->call_data->self_object(),
*user_data->compute_context,
node_,
bsocket.identifier,
bsocket.name));
storage->attributes.append({output_bsocket_index, attribute_id});
return attribute_id;
};
bool used_non_attribute_output_exists = false;
for (const int output_bsocket_index : node_.output_sockets().index_range()) {
const bNodeSocket &output_bsocket = node_.output_socket(output_bsocket_index);
@@ -278,8 +211,7 @@ class LazyFunctionForGeometryNode : public LazyFunction {
if (params.output_was_set(lf_index)) {
continue;
}
this->output_anonymous_attribute_field(
params, lf_index, output_bsocket, get_output_attribute_id(output_bsocket_index));
this->output_anonymous_attribute_field(params, *user_data, lf_index, output_bsocket);
}
else {
if (output_usage == lf::ValueUsage::Used) {
@@ -305,13 +237,17 @@ class LazyFunctionForGeometryNode : public LazyFunction {
return;
}
auto get_anonymous_attribute_name = [&](const int i) {
return this->anonymous_attribute_name_for_output(*user_data, i);
};
GeoNodeExecParams geo_params{
node_,
params,
context,
own_lf_graph_info_.mapping.lf_input_index_for_output_bsocket_usage,
own_lf_graph_info_.mapping.lf_input_index_for_attribute_propagation_to_output,
get_output_attribute_id};
get_anonymous_attribute_name};
geo_eval_log::TimePoint start_time = geo_eval_log::Clock::now();
node_.typeinfo->geometry_node_execute(geo_params);
@@ -324,23 +260,6 @@ class LazyFunctionForGeometryNode : public LazyFunction {
}
}
/**
* Output the given anonymous attribute id as a field.
*/
void output_anonymous_attribute_field(lf::Params &params,
const int lf_index,
const bNodeSocket &bsocket,
AnonymousAttributeIDPtr attribute_id) const
{
GField output_field{std::make_shared<AnonymousAttributeFieldInput>(
std::move(attribute_id),
*bsocket.typeinfo->base_cpp_type,
fmt::format(TIP_("{} node"), node_.label_or_name()))};
void *r_value = params.get_output_data_ptr(lf_index);
new (r_value) SocketValueVariant(std::move(output_field));
params.output_set(lf_index);
}
std::string input_name(const int index) const override
{
for (const bNodeSocket *bsocket : node_.output_sockets()) {
@@ -368,6 +287,33 @@ class LazyFunctionForGeometryNode : public LazyFunction {
{
return outputs_[index].debug_name;
}
void output_anonymous_attribute_field(lf::Params &params,
const GeoNodesLFUserData &user_data,
const int lf_index,
const bNodeSocket &socket) const
{
std::string attribute_name = this->anonymous_attribute_name_for_output(user_data,
socket.index());
std::string socket_inspection_name = make_anonymous_attribute_socket_inspection_string(socket);
auto attribute_field = std::make_shared<AttributeFieldInput>(
std::move(attribute_name),
*socket.typeinfo->base_cpp_type,
std::move(socket_inspection_name));
void *r_value = params.get_output_data_ptr(lf_index);
new (r_value) SocketValueVariant(GField(std::move(attribute_field)));
params.output_set(lf_index);
}
std::string anonymous_attribute_name_for_output(const GeoNodesLFUserData &user_data,
const int output_index) const
{
return bke::hash_to_anonymous_attribute_name(user_data.call_data->self_object()->id.name,
user_data.compute_context->hash(),
node_.identifier,
node_.output_socket(output_index).identifier);
}
};
/**
@@ -502,6 +448,17 @@ void set_default_remaining_node_outputs(lf::Params &params, const bNode &node)
}
}
std::string make_anonymous_attribute_socket_inspection_string(const bNodeSocket &socket)
{
return make_anonymous_attribute_socket_inspection_string(socket.owner_node().label_or_name(),
socket.name);
}
std::string make_anonymous_attribute_socket_inspection_string(StringRef node_name,
StringRef socket_name)
{
return fmt::format(TIP_("\"{}\" from {}"), socket_name, node_name);
}
static void execute_multi_function_on_value_variant__single(
const MultiFunction &fn,
const Span<SocketValueVariant *> input_values,
@@ -1384,13 +1341,15 @@ class LazyFunctionForAnonymousAttributeSetExtract : public lf::LazyFunction {
if (value_variant->is_context_dependent_field()) {
const GField &field = value_variant->get<GField>();
field.node().for_each_field_input_recursive([&](const FieldInput &field_input) {
if (const auto *attr_field_input = dynamic_cast<const AnonymousAttributeFieldInput *>(
&field_input))
if (const auto *attr_field_input = dynamic_cast<const AttributeFieldInput *>(&field_input))
{
if (!attributes.names) {
attributes.names = std::make_shared<Set<std::string>>();
const StringRef name = attr_field_input->attribute_name();
if (bke::attribute_name_is_anonymous(name)) {
if (!attributes.names) {
attributes.names = std::make_shared<Set<std::string>>();
}
attributes.names->add_as(name);
}
attributes.names->add_as(attr_field_input->anonymous_id()->name());
}
});
}