Fix: Removing attributes from UI invalidates caches
Use the new attribute API to implement the attribute remove function used by RNA, except for BMesh attributes. Currently, removing curve attributes from the panel in the property editor does not mark the relevant caches dirty (for example, the cache of curve type counts), because that behavior is implemented with the new attribute API. Also, eventually we want to merge the two APIs, and removing an attribute is the first function that can be partially implemented with the new API. Differential Revision: https://developer.blender.org/D15495
This commit is contained in:
parent
0c3851d31f
commit
c94c0d988a
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
@ -24,7 +25,7 @@
|
|||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_curves.h"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_pointcloud.h"
|
||||
|
@ -89,6 +90,36 @@ static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
|
|||
}
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
static std::optional<blender::bke::MutableAttributeAccessor> get_attribute_accessor_for_write(
|
||||
ID &id)
|
||||
{
|
||||
switch (GS(id.name)) {
|
||||
case ID_ME: {
|
||||
Mesh &mesh = reinterpret_cast<Mesh &>(id);
|
||||
/* The attribute API isn't implemented for BMesh, so edit mode meshes are not supported. */
|
||||
BLI_assert(mesh.edit_mesh == nullptr);
|
||||
return mesh_attributes_for_write(mesh);
|
||||
}
|
||||
case ID_PT: {
|
||||
PointCloud &pointcloud = reinterpret_cast<PointCloud &>(id);
|
||||
return pointcloud_attributes_for_write(pointcloud);
|
||||
}
|
||||
case ID_CV: {
|
||||
Curves &curves_id = reinterpret_cast<Curves &>(id);
|
||||
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
|
||||
return curves.attributes_for_write();
|
||||
}
|
||||
default: {
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
bool BKE_id_attributes_supported(const ID *id)
|
||||
{
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
|
@ -242,6 +273,7 @@ CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList
|
|||
|
||||
bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
if (BKE_id_attribute_required(id, name)) {
|
||||
BKE_report(reports, RPT_ERROR, "Attribute is required and can't be removed");
|
||||
return false;
|
||||
|
@ -266,12 +298,9 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
|
|||
ATTR_FALLTHROUGH;
|
||||
}
|
||||
default:
|
||||
for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
|
||||
if (CustomData *data = info[domain].customdata) {
|
||||
if (CustomData_free_layer_named(data, name, info[domain].length)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (std::optional<MutableAttributeAccessor> attributes = get_attribute_accessor_for_write(
|
||||
*id)) {
|
||||
return attributes->remove(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -319,8 +319,8 @@ GAttributeWriter BuiltinCustomDataLayerProvider::try_get_for_write(void *owner)
|
|||
}
|
||||
|
||||
std::function<void()> tag_modified_fn;
|
||||
if (update_on_write_ != nullptr) {
|
||||
tag_modified_fn = [owner, update = update_on_write_]() { update(owner); };
|
||||
if (update_on_change_ != nullptr) {
|
||||
tag_modified_fn = [owner, update = update_on_change_]() { update(owner); };
|
||||
}
|
||||
|
||||
return {as_write_attribute_(data, element_num), domain_, std::move(tag_modified_fn)};
|
||||
|
@ -336,12 +336,19 @@ bool BuiltinCustomDataLayerProvider::try_delete(void *owner) const
|
|||
return {};
|
||||
}
|
||||
|
||||
auto update = [&]() {
|
||||
if (update_on_change_ != nullptr) {
|
||||
update_on_change_(owner);
|
||||
}
|
||||
};
|
||||
|
||||
const int element_num = custom_data_access_.get_element_num(owner);
|
||||
if (stored_as_named_attribute_) {
|
||||
if (CustomData_free_layer_named(custom_data, name_.c_str(), element_num)) {
|
||||
if (custom_data_access_.update_custom_data_pointers) {
|
||||
custom_data_access_.update_custom_data_pointers(owner);
|
||||
}
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -352,8 +359,10 @@ bool BuiltinCustomDataLayerProvider::try_delete(void *owner) const
|
|||
if (custom_data_access_.update_custom_data_pointers) {
|
||||
custom_data_access_.update_custom_data_pointers(owner);
|
||||
}
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -226,12 +226,12 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
|
|||
using AsReadAttribute = GVArray (*)(const void *data, int element_num);
|
||||
using AsWriteAttribute = GVMutableArray (*)(void *data, int element_num);
|
||||
using UpdateOnRead = void (*)(const void *owner);
|
||||
using UpdateOnWrite = void (*)(void *owner);
|
||||
using UpdateOnChange = void (*)(void *owner);
|
||||
const eCustomDataType stored_type_;
|
||||
const CustomDataAccessInfo custom_data_access_;
|
||||
const AsReadAttribute as_read_attribute_;
|
||||
const AsWriteAttribute as_write_attribute_;
|
||||
const UpdateOnWrite update_on_write_;
|
||||
const UpdateOnChange update_on_change_;
|
||||
bool stored_as_named_attribute_;
|
||||
|
||||
public:
|
||||
|
@ -245,14 +245,14 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
|
|||
const CustomDataAccessInfo custom_data_access,
|
||||
const AsReadAttribute as_read_attribute,
|
||||
const AsWriteAttribute as_write_attribute,
|
||||
const UpdateOnWrite update_on_write)
|
||||
const UpdateOnChange update_on_write)
|
||||
: BuiltinAttributeProvider(
|
||||
std::move(attribute_name), domain, attribute_type, creatable, writable, deletable),
|
||||
stored_type_(stored_type),
|
||||
custom_data_access_(custom_data_access),
|
||||
as_read_attribute_(as_read_attribute),
|
||||
as_write_attribute_(as_write_attribute),
|
||||
update_on_write_(update_on_write),
|
||||
update_on_change_(update_on_write),
|
||||
stored_as_named_attribute_(data_type_ == stored_type_)
|
||||
{
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue