Fix T90026: attributes added in editmode are lost on modeswitch

When exiting editmode, customdata [and thus attributes] are copied from
**BMesh** to **Mesh** (in `BM_mesh_bm_to_me`).
When adding attributes, these were always added via
`CustomData_add_layer_named` only.
Instead (if we are in mesh editmode), we need to go through
`BM_data_layer_add_named` to properly update the **BMesh** (see
`update_data_blocks`) so we have stuff available to copy back to
**Mesh** when exiting editmode.
Same is done for removing (also going through BMesh).

This is now done, DomainInfo is updated to point to BMesh (instead of
Mesh) customdata when in editmode.

Maniphest Tasks: T90026

Differential Revision: https://developer.blender.org/D11998
This commit is contained in:
Philipp Oeser
2021-07-22 14:05:55 +02:00
parent 0e8d1c6bcf
commit 97712b018d

View File

@@ -39,6 +39,7 @@
#include "BKE_attribute.h" #include "BKE_attribute.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_hair.h" #include "BKE_hair.h"
#include "BKE_pointcloud.h" #include "BKE_pointcloud.h"
#include "BKE_report.h" #include "BKE_report.h"
@@ -63,6 +64,19 @@ static void get_domains(ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
} }
case ID_ME: { case ID_ME: {
Mesh *mesh = (Mesh *)id; Mesh *mesh = (Mesh *)id;
BMEditMesh *em = mesh->edit_mesh;
if (em != NULL) {
BMesh *bm = em->bm;
info[ATTR_DOMAIN_POINT].customdata = &bm->vdata;
info[ATTR_DOMAIN_POINT].length = bm->totvert;
info[ATTR_DOMAIN_EDGE].customdata = &bm->edata;
info[ATTR_DOMAIN_EDGE].length = bm->totedge;
info[ATTR_DOMAIN_CORNER].customdata = &bm->ldata;
info[ATTR_DOMAIN_CORNER].length = bm->totloop;
info[ATTR_DOMAIN_FACE].customdata = &bm->pdata;
info[ATTR_DOMAIN_FACE].length = bm->totface;
}
else {
info[ATTR_DOMAIN_POINT].customdata = &mesh->vdata; info[ATTR_DOMAIN_POINT].customdata = &mesh->vdata;
info[ATTR_DOMAIN_POINT].length = mesh->totvert; info[ATTR_DOMAIN_POINT].length = mesh->totvert;
info[ATTR_DOMAIN_EDGE].customdata = &mesh->edata; info[ATTR_DOMAIN_EDGE].customdata = &mesh->edata;
@@ -71,6 +85,7 @@ static void get_domains(ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
info[ATTR_DOMAIN_CORNER].length = mesh->totloop; info[ATTR_DOMAIN_CORNER].length = mesh->totloop;
info[ATTR_DOMAIN_FACE].customdata = &mesh->pdata; info[ATTR_DOMAIN_FACE].customdata = &mesh->pdata;
info[ATTR_DOMAIN_FACE].length = mesh->totpoly; info[ATTR_DOMAIN_FACE].length = mesh->totpoly;
}
break; break;
} }
case ID_HA: { case ID_HA: {
@@ -146,7 +161,24 @@ CustomDataLayer *BKE_id_attribute_new(
return NULL; return NULL;
} }
switch (GS(id->name)) {
case ID_ME: {
Mesh *me = (Mesh *)id;
BMEditMesh *em = me->edit_mesh;
if (em != NULL) {
BM_data_layer_add_named(em->bm, customdata, type, name);
}
else {
CustomData_add_layer_named(customdata, type, CD_DEFAULT, NULL, info[domain].length, name); CustomData_add_layer_named(customdata, type, CD_DEFAULT, NULL, info[domain].length, name);
}
break;
}
default: {
CustomData_add_layer_named(customdata, type, CD_DEFAULT, NULL, info[domain].length, name);
break;
}
}
const int index = CustomData_get_named_layer_index(customdata, type, name); const int index = CustomData_get_named_layer_index(customdata, type, name);
return (index == -1) ? NULL : &(customdata->layers[index]); return (index == -1) ? NULL : &(customdata->layers[index]);
} }
@@ -168,8 +200,26 @@ bool BKE_id_attribute_remove(ID *id, CustomDataLayer *layer, ReportList *reports
return false; return false;
} }
switch (GS(id->name)) {
case ID_ME: {
Mesh *me = (Mesh *)id;
BMEditMesh *em = me->edit_mesh;
if (em != NULL) {
BM_data_layer_free(em->bm, customdata, layer->type);
}
else {
const int length = BKE_id_attribute_data_length(id, layer); const int length = BKE_id_attribute_data_length(id, layer);
CustomData_free_layer(customdata, layer->type, length, index); CustomData_free_layer(customdata, layer->type, length, index);
}
break;
}
default: {
const int length = BKE_id_attribute_data_length(id, layer);
CustomData_free_layer(customdata, layer->type, length, index);
break;
}
}
return true; return true;
} }
@@ -316,7 +366,7 @@ CustomData *BKE_id_attributes_iterator_next_domain(ID *id, CustomDataLayer *laye
for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) { for (AttributeDomain domain = 0; domain < ATTR_DOMAIN_NUM; domain++) {
CustomData *customdata = info[domain].customdata; CustomData *customdata = info[domain].customdata;
if (customdata && customdata->layers) { if (customdata && customdata->layers && customdata->totlayer) {
if (customdata->layers == layers) { if (customdata->layers == layers) {
use_next = true; use_next = true;
} }