From b1033913f7a43648f60e056ba9faf22141130359 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 7 Feb 2023 13:35:41 -0500 Subject: [PATCH] Fix #100957: Dyntopo shows false positive data loss warnings Because of #95965, some attributes are stored as generic attributes in Mesh but have special handling for the conversion to BMesh. Expose a function to tell whether certain attribute names are handled specially in the conversion, and refactor the error checking process to use it. Also check for generic attributes on the face domain which wasn't done before. --- .../blender/blenkernel/intern/customdata.cc | 16 +------ .../bmesh/intern/bmesh_mesh_convert.cc | 14 ++++++ .../blender/bmesh/intern/bmesh_mesh_convert.h | 10 ++++ .../editors/sculpt_paint/sculpt_dyntopo.cc | 46 +++++++++++++------ 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index b71a705eecb..0e7e81a2383 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2289,26 +2289,12 @@ bool CustomData_merge(const CustomData *source, return changed; } -static bool attribute_stored_in_bmesh_flag(const StringRef name) -{ - return ELEM(name, - "position", - ".hide_vert", - ".hide_edge", - ".hide_poly", - ".select_vert", - ".select_edge", - ".select_poly", - "material_index", - "sharp_edge"); -} - CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src, const eCustomDataMask mask) { Vector dst_layers; for (const CustomDataLayer &layer : Span{src->layers, src->totlayer}) { - if (attribute_stored_in_bmesh_flag(layer.name)) { + if (BM_attribute_stored_in_bmesh_builtin(layer.name)) { continue; } if (!(mask & CD_TYPE_AS_MASK(layer.type))) { diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index d58337400a2..0980f8d1918 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -133,6 +133,20 @@ static char bm_face_flag_to_mflag(const BMFace *f) return ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0); } +bool BM_attribute_stored_in_bmesh_builtin(const StringRef name) +{ + return ELEM(name, + "position", + ".hide_vert", + ".hide_edge", + ".hide_poly", + ".select_vert", + ".select_edge", + ".select_poly", + "material_index", + "sharp_edge"); +} + /* Static function for alloc (duplicate in modifiers_bmesh.c) */ static BMFace *bm_face_create_from_mpoly(BMesh &bm, Span loops, diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.h b/source/blender/bmesh/intern/bmesh_mesh_convert.h index 82b6d41b19b..bd6492d6ec6 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.h +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.h @@ -9,6 +9,16 @@ #include "bmesh.h" +#ifdef __cplusplus +# include "BLI_string_ref.hh" + +/** + * \return Whether attributes with the given name are stored in special flags or fields in BMesh + * rather than in the regular custom data blocks. + */ +bool BM_attribute_stored_in_bmesh_builtin(const blender::StringRef name); +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc index a77b73ebaae..232839c6863 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc @@ -274,15 +274,14 @@ static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator * /*op*/) return OPERATOR_FINISHED; } - static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoWarnFlag flag) { uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Warning!"), ICON_ERROR); uiLayout *layout = UI_popup_menu_layout(pup); if (flag & (DYNTOPO_WARN_VDATA | DYNTOPO_WARN_EDATA | DYNTOPO_WARN_LDATA)) { - const char *msg_error = TIP_("Vertex Data Detected!"); - const char *msg = TIP_("Dyntopo will not preserve vertex colors, UVs, or other customdata"); + const char *msg_error = TIP_("Attribute Data Detected"); + const char *msg = TIP_("Dyntopo will not preserve colors, UVs, or other attributes"); uiItemL(layout, msg_error, ICON_INFO); uiItemL(layout, msg, ICON_NONE); uiItemS(layout); @@ -305,6 +304,24 @@ static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoW return OPERATOR_INTERFACE; } +static bool dyntopo_supports_customdata_type(const CustomDataLayer &layer) +{ + if (CD_TYPE_AS_MASK(layer.type) & CD_MASK_PROP_ALL) { + if (layer.name[0] == '\0') { + return false; + } + /* Some data is stored as generic attributes on #Mesh but in flags or field on #BMesh. */ + return BM_attribute_stored_in_bmesh_builtin(layer.name); + } + /* Some layers just encode #Mesh topology or are handled as special cases for dyntopo. */ + return ELEM(layer.type, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX); +} + +static bool dyntopo_supports_customdata_layers(const blender::Span layers) +{ + return std::all_of(layers.begin(), layers.end(), dyntopo_supports_customdata_type); +} + enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob) { Mesh *me = static_cast(ob->data); @@ -315,18 +332,17 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob) BLI_assert(ss->bm == nullptr); UNUSED_VARS_NDEBUG(ss); - for (int i = 0; i < CD_NUMTYPES; i++) { - if (!ELEM(i, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX)) { - if (CustomData_has_layer(&me->vdata, i)) { - flag |= DYNTOPO_WARN_VDATA; - } - if (CustomData_has_layer(&me->edata, i)) { - flag |= DYNTOPO_WARN_EDATA; - } - if (CustomData_has_layer(&me->ldata, i)) { - flag |= DYNTOPO_WARN_LDATA; - } - } + if (!dyntopo_supports_customdata_layers({me->vdata.layers, me->vdata.totlayer})) { + flag |= DYNTOPO_WARN_VDATA; + } + if (!dyntopo_supports_customdata_layers({me->edata.layers, me->edata.totlayer})) { + flag |= DYNTOPO_WARN_EDATA; + } + if (!dyntopo_supports_customdata_layers({me->pdata.layers, me->pdata.totlayer})) { + flag |= DYNTOPO_WARN_LDATA; + } + if (!dyntopo_supports_customdata_layers({me->ldata.layers, me->ldata.totlayer})) { + flag |= DYNTOPO_WARN_LDATA; } { -- 2.30.2