Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-06-04 16:45:21 +0300
committerHans Goudey <h.goudey@me.com>2022-06-04 16:45:21 +0300
commit08d43e01cbf9d4025cc0b28f04cf0d7eb93ce947 (patch)
treef9082c19eb661fb6b7dee04421ad20b01702e047
parentf6b729347017edbf98452c17c1a809728129ed33 (diff)
Fix changes persisting when exiting edit mode
-rw-r--r--source/blender/blenkernel/BKE_customdata.h2
-rw-r--r--source/blender/blenkernel/intern/customdata.cc14
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.cc97
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c4
4 files changed, 87 insertions, 30 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 63fea3ddb3f..95a32959d94 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -244,6 +244,8 @@ void *CustomData_add_layer_anonymous(struct CustomData *data,
*/
bool CustomData_free_layer(struct CustomData *data, int type, int totelem, int index);
+bool CustomData_free_layer_named(struct CustomData *data, const char *name, const int totelem);
+
/**
* Frees the layer index with the give type.
* returns 1 on success, 0 if no layer with the given type is found.
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index 5ea8daeaa40..f87f06da800 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -2327,7 +2327,7 @@ bool CustomData_merge(const CustomData *source,
static bool layer_stored_in_bmesh(const StringRef name)
{
- return ELEM(name, ".hide_face", ".hide_edge", ".hide_face");
+ return ELEM(name, ".hide_vert", ".hide_edge", ".hide_face");
}
static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src)
@@ -2948,6 +2948,18 @@ bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
return true;
}
+bool CustomData_free_layer_named(CustomData *data, const char *name, const int totelem)
+{
+ for (const int i : IndexRange(data->totlayer)) {
+ const CustomDataLayer &layer = data->layers[i];
+ if (StringRef(layer.name) == name) {
+ CustomData_free_layer(data, layer.type, totelem, i);
+ return true;
+ }
+ }
+ return false;
+}
+
bool CustomData_free_layer_active(CustomData *data, int type, int totelem)
{
const int index = CustomData_get_active_layer_index(data, type);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc
index 35ce9b6b9ff..b4a319f2fe5 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc
@@ -83,8 +83,10 @@
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
#include "BLI_span.hh"
+#include "BLI_string_ref.hh"
#include "BKE_customdata.h"
+#include "BKE_geometry_set.hh"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_multires.h"
@@ -105,6 +107,7 @@ using blender::Array;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
+using blender::StringRef;
void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag)
{
@@ -919,22 +922,57 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e)
}
}
-static void ensure_bool_layer(MutableSpan<bool> &values,
- CustomData &data,
- const char *name,
- const int num)
+template<typename GetFn>
+static void write_elem_flag_to_attribute(MeshComponent &mesh,
+ const StringRef attribute_name,
+ const eAttrDomain domain,
+ const bool do_write,
+ const GetFn &get_fn)
{
- if (values.is_empty()) {
- if (void *layer_data = CustomData_get_layer_named(&data, CD_PROP_BOOL, name)) {
- values = {(bool *)layer_data, num};
- }
+ if (!do_write) {
+ mesh.attribute_try_delete(attribute_name);
}
- if (values.is_empty()) {
- values = {(bool *)CustomData_add_layer_named(&data, CD_PROP_BOOL, CD_CALLOC, NULL, num, name),
- num};
+ else {
+ blender::bke::OutputAttribute_Typed<bool> attribute =
+ mesh.attribute_try_get_for_output_only<bool>(attribute_name, domain);
+ MutableSpan<bool> hide = attribute.as_span();
+ for (const int i : hide.index_range()) {
+ hide[i] = get_fn(i);
+ }
+ attribute.save();
}
}
+static void convert_bmesh_hide_flags_to_mesh_attributes(BMesh &bm,
+ const bool need_hide_vert,
+ const bool need_hide_edge,
+ const bool need_hide_face,
+ Mesh &mesh)
+{
+ /* The "hide" attributes are stored as flags on #BMesh. */
+ BLI_assert(CustomData_get_layer_named(&bm.vdata, CD_PROP_BOOL, ".hide_vert") == nullptr);
+ BLI_assert(CustomData_get_layer_named(&bm.edata, CD_PROP_BOOL, ".edge_vert") == nullptr);
+ BLI_assert(CustomData_get_layer_named(&bm.pdata, CD_PROP_BOOL, ".face_vert") == nullptr);
+
+ MeshComponent component;
+ component.replace(&mesh, GeometryOwnershipType::Editable);
+
+ BM_mesh_elem_table_ensure(&bm, BM_VERT | BM_EDGE | BM_FACE);
+
+ write_elem_flag_to_attribute(
+ component, ".hide_vert", ATTR_DOMAIN_POINT, need_hide_vert, [&](const int i) {
+ return BM_elem_flag_test(BM_vert_at_index(&bm, i), BM_ELEM_HIDDEN);
+ });
+ write_elem_flag_to_attribute(
+ component, ".hide_edge", ATTR_DOMAIN_EDGE, need_hide_edge, [&](const int i) {
+ return BM_elem_flag_test(BM_edge_at_index(&bm, i), BM_ELEM_HIDDEN);
+ });
+ write_elem_flag_to_attribute(
+ component, ".hide_face", ATTR_DOMAIN_FACE, need_hide_face, [&](const int i) {
+ return BM_elem_flag_test(BM_face_at_index(&bm, i), BM_ELEM_HIDDEN);
+ });
+}
+
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
{
MEdge *med;
@@ -993,9 +1031,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
- MutableSpan<bool> vert_hide;
- MutableSpan<bool> edge_hide;
- MutableSpan<bool> face_hide;
+ bool need_hide_vert = false;
+ bool need_hide_edge = false;
+ bool need_hide_face = false;
/* Clear normals on the mesh completely, since the original vertex and polygon count might be
* different than the BMesh's. */
@@ -1012,8 +1050,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
mvert->flag = BM_vert_flag_to_mflag(v);
if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- ensure_bool_layer(vert_hide, me->vdata, ".hide_vert", me->totvert);
- vert_hide[i] = true;
+ need_hide_vert = true;
}
BM_elem_index_set(v, i); /* set_inline */
@@ -1040,8 +1077,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
med->flag = BM_edge_flag_to_mflag(e);
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- ensure_bool_layer(edge_hide, me->edata, ".hide_edge", me->totedge);
- edge_hide[i] = true;
+ need_hide_edge = true;
}
BM_elem_index_set(e, i); /* set_inline */
@@ -1073,9 +1109,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
mpoly->mat_nr = f->mat_nr;
mpoly->flag = BM_face_flag_to_mflag(f);
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- ensure_bool_layer(face_hide, me->pdata, ".hide_face", me->totpoly);
- face_hide[i] = true;
+ need_hide_face = true;
}
+
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
mloop->e = BM_elem_index_get(l_iter->e);
@@ -1167,6 +1203,9 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
}
}
+ convert_bmesh_hide_flags_to_mesh_attributes(
+ *bm, need_hide_vert, need_hide_edge, need_hide_face, *me);
+
BKE_mesh_update_customdata_pointers(me, false);
{
@@ -1260,9 +1299,9 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
- MutableSpan<bool> vert_hide;
- MutableSpan<bool> edge_hide;
- MutableSpan<bool> face_hide;
+ bool need_hide_vert = false;
+ bool need_hide_edge = false;
+ bool need_hide_face = false;
/* Clear normals on the mesh completely, since the original vertex and polygon count might be
* different than the BMesh's. */
@@ -1279,8 +1318,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
mv->flag = BM_vert_flag_to_mflag(eve);
if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- ensure_bool_layer(vert_hide, me->vdata, ".hide_vert", me->totvert);
- vert_hide[i] = true;
+ need_hide_vert = true;
}
if (cd_vert_bweight_offset != -1) {
@@ -1305,8 +1343,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
med->flag = BM_edge_flag_to_mflag(eed);
if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
- ensure_bool_layer(edge_hide, me->edata, ".hide_edge", me->totedge);
- edge_hide[i] = true;
+ need_hide_edge = true;
}
/* Handle this differently to editmode switching,
@@ -1339,8 +1376,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
mp->totloop = efa->len;
mp->flag = BM_face_flag_to_mflag(efa);
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- ensure_bool_layer(face_hide, me->pdata, ".hide_face", me->totpoly);
- face_hide[i] = true;
+ need_hide_face = true;
}
mp->loopstart = j;
@@ -1362,5 +1398,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
}
bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
+ convert_bmesh_hide_flags_to_mesh_attributes(
+ *bm, need_hide_vert, need_hide_edge, need_hide_face, *me);
+
me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
}
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index d75c92f963f..4bd3ef166f3 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -594,6 +594,10 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo
/* Uncomment for troubleshooting. */
// BM_mesh_validate(em->bm);
+ /* Copy the ID name characters to the mesh so code that depends on accessing the ID type can work
+ * on it. Necessary to use the attribute API. */
+ strcpy(um->me.id.name, "ME");
+
BM_mesh_bm_to_me(
NULL,
em->bm,