diff options
-rw-r--r-- | source/blender/blenkernel/BKE_customdata.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.cc | 14 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh_convert.cc | 97 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_undo.c | 4 |
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, |