Attributes: Add function to rename attribute

This is implemented by removing the attribute and adding it again with
a different name. In the expected case though, implicit sharing is used
to avoid copying the array.

For now this doesn't rename UV sublayers or replace active/default color
attribute names. It's not clear where that should happen, but for now
things are clearer if those stay at a higher level.
This commit is contained in:
Jacques Lucke
2023-04-27 09:54:40 -04:00
committed by Hans Goudey
parent 3c0b15b7eb
commit 18f4fd6b85
2 changed files with 40 additions and 0 deletions

View File

@@ -653,6 +653,11 @@ class MutableAttributeAccessor : public AttributeAccessor {
return {};
}
/**
* Replace the existing attribute with a new one with a different name.
*/
bool rename(const AttributeIDRef &old_attribute_id, const AttributeIDRef &new_attribute_id);
/**
* Create a new attribute.
* \return True, when a new attribute has been created. False, when it's not possible to create

View File

@@ -911,6 +911,41 @@ GSpanAttributeWriter MutableAttributeAccessor::lookup_or_add_for_write_only_span
return {};
}
bool MutableAttributeAccessor::rename(const AttributeIDRef &old_attribute_id,
const AttributeIDRef &new_attribute_id)
{
if (old_attribute_id == new_attribute_id) {
return true;
}
if (this->contains(new_attribute_id)) {
return false;
}
const GAttributeReader old_attribute = this->lookup(old_attribute_id);
if (!old_attribute) {
return false;
}
const eCustomDataType type = cpp_type_to_custom_data_type(old_attribute.varray.type());
if (old_attribute.sharing_info != nullptr && old_attribute.varray.is_span()) {
if (!this->add(new_attribute_id,
old_attribute.domain,
type,
AttributeInitShared{old_attribute.varray.get_internal_span().data(),
*old_attribute.sharing_info})) {
return false;
}
}
else {
if (!this->add(new_attribute_id,
old_attribute.domain,
type,
AttributeInitVArray{old_attribute.varray})) {
return false;
}
}
this->remove(old_attribute_id);
return true;
}
fn::GField AttributeValidator::validate_field_if_necessary(const fn::GField &field) const
{
if (function) {