diff options
author | Hans Goudey <h.goudey@me.com> | 2020-09-01 20:35:14 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2020-09-01 20:38:05 +0300 |
commit | baca8611e5fe4b3dcd6f5065fb125bc0a9d65934 (patch) | |
tree | bb1230387cd53b15f9621f10c4d0e5e2050b5580 /source/blender/editors/mesh | |
parent | 31705201dddebf7e3be5c4533b89f380aad1ede1 (diff) | |
parent | 2930d4fcea405985f2212c5f28c061af7c4849f8 (diff) |
Merge branch 'master' into active-fcurve-keyframeactive-fcurve-keyframe
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r-- | source/blender/editors/mesh/CMakeLists.txt | 4 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_intersect.c | 177 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife.c | 18 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_mask_extract.c | 16 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_preselect_edgering.c | 4 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_preselect_elem.c | 4 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 36 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 6 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_utils.c | 73 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_data.c | 4 | ||||
-rw-r--r-- | source/blender/editors/mesh/meshtools.c | 6 |
11 files changed, 237 insertions, 111 deletions
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index e41445aef09..589b51ce942 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -93,6 +93,10 @@ if(WITH_BULLET) add_definitions(-DWITH_BULLET) endif() +if(WITH_GMP) + add_definitions(-DWITH_GMP) +endif() + add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_mesh "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 97bd6ee0039..1b5e374b2a7 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -39,6 +39,9 @@ #include "WM_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "ED_mesh.h" #include "ED_screen.h" @@ -46,6 +49,7 @@ #include "mesh_intern.h" /* own include */ +#include "tools/bmesh_boolean.h" #include "tools/bmesh_intersect.h" #include "tools/bmesh_separate.h" @@ -134,6 +138,11 @@ enum { ISECT_SEPARATE_NONE = 2, }; +enum { + ISECT_SOLVER_FAST = 0, + ISECT_SOLVER_EXACT = 1, +}; + static int edbm_intersect_exec(bContext *C, wmOperator *op) { const int mode = RNA_enum_get(op->ptr, "mode"); @@ -142,6 +151,14 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op) bool use_separate_cut = false; const int separate_mode = RNA_enum_get(op->ptr, "separate_mode"); const float eps = RNA_float_get(op->ptr, "threshold"); +#ifdef WITH_GMP + const bool exact = RNA_enum_get(op->ptr, "solver") == ISECT_SOLVER_EXACT; +#else + if (RNA_enum_get(op->ptr, "solver") == ISECT_SOLVER_EXACT) { + BKE_report(op->reports, RPT_WARNING, "Compiled without GMP, using fast solver"); + } + const bool exact = false; +#endif bool use_self; bool has_isect; @@ -186,19 +203,25 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op) continue; } - has_isect = BM_mesh_intersect(em->bm, - em->looptris, - em->tottri, - test_fn, - NULL, - use_self, - use_separate_all, - true, - true, - true, - true, - -1, - eps); + if (exact) { + has_isect = BM_mesh_boolean_knife( + em->bm, em->looptris, em->tottri, test_fn, NULL, use_self, use_separate_all); + } + else { + has_isect = BM_mesh_intersect(em->bm, + em->looptris, + em->tottri, + test_fn, + NULL, + use_self, + use_separate_all, + true, + true, + true, + true, + -1, + eps); + } if (use_separate_cut) { /* detach selected/un-selected faces */ @@ -220,6 +243,34 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static void edbm_intersect_ui(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + uiLayout *row; + PointerRNA ptr; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + + bool use_exact = RNA_enum_get(&ptr, "solver") == ISECT_SOLVER_EXACT; + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + row = uiLayoutRow(layout, false); + uiItemR(row, &ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemS(layout); + row = uiLayoutRow(layout, false); + uiItemR(row, &ptr, "separate_mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemS(layout); + + row = uiLayoutRow(layout, false); + uiItemR(row, &ptr, "solver", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemS(layout); + + if (!use_exact) { + uiItemR(layout, &ptr, "threshold", 0, NULL, ICON_NONE); + } +} + void MESH_OT_intersect(struct wmOperatorType *ot) { static const EnumPropertyItem isect_mode_items[] = { @@ -243,6 +294,12 @@ void MESH_OT_intersect(struct wmOperatorType *ot) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem isect_intersect_solver_items[] = { + {ISECT_SOLVER_FAST, "FAST", 0, "Fast", "Faster Solver, some limitations"}, + {ISECT_SOLVER_EXACT, "EXACT", 0, "Exact", "Exact Solver, slower, handles more cases"}, + {0, NULL, 0, NULL, NULL}, + }; + /* identifiers */ ot->name = "Intersect (Knife)"; ot->description = "Cut an intersection into faces"; @@ -251,6 +308,7 @@ void MESH_OT_intersect(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_intersect_exec; ot->poll = ED_operator_editmesh; + ot->ui = edbm_intersect_ui; /* props */ RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", ""); @@ -258,6 +316,12 @@ void MESH_OT_intersect(struct wmOperatorType *ot) ot->srna, "separate_mode", isect_separate_items, ISECT_SEPARATE_CUT, "Separate Mode", ""); RNA_def_float_distance( ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001); + RNA_def_enum(ot->srna, + "solver", + isect_intersect_solver_items, + ISECT_SOLVER_EXACT, + "Solver", + "Which Intersect solver to use"); /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -280,6 +344,15 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op) { const int boolean_operation = RNA_enum_get(op->ptr, "operation"); bool use_swap = RNA_boolean_get(op->ptr, "use_swap"); + bool use_self = RNA_boolean_get(op->ptr, "use_self"); +#ifdef WITH_GMP + const bool use_exact = RNA_enum_get(op->ptr, "solver") == ISECT_SOLVER_EXACT; +#else + if (RNA_enum_get(op->ptr, "solver") == ISECT_SOLVER_EXACT) { + BKE_report(op->reports, RPT_WARNING, "Compiled without GMP, using fast solver"); + } + const bool use_exact = false; +#endif const float eps = RNA_float_get(op->ptr, "threshold"); int (*test_fn)(BMFace *, void *); bool has_isect; @@ -298,19 +371,25 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op) continue; } - has_isect = BM_mesh_intersect(em->bm, - em->looptris, - em->tottri, - test_fn, - NULL, - false, - false, - true, - true, - false, - true, - boolean_operation, - eps); + if (use_exact) { + has_isect = BM_mesh_boolean( + em->bm, em->looptris, em->tottri, test_fn, NULL, use_self, boolean_operation); + } + else { + has_isect = BM_mesh_intersect(em->bm, + em->looptris, + em->tottri, + test_fn, + NULL, + false, + false, + true, + true, + false, + true, + boolean_operation, + eps); + } edbm_intersect_select(em, obedit->data, has_isect); @@ -326,6 +405,34 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static void edbm_intersect_boolean_ui(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + uiLayout *row; + PointerRNA ptr; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + + bool use_exact = RNA_enum_get(&ptr, "solver") == ISECT_SOLVER_EXACT; + + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + + row = uiLayoutRow(layout, false); + uiItemR(row, &ptr, "operation", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemS(layout); + + row = uiLayoutRow(layout, false); + uiItemR(row, &ptr, "solver", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemS(layout); + + uiItemR(layout, &ptr, "use_swap", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "use_self", 0, NULL, ICON_NONE); + if (!use_exact) { + uiItemR(layout, &ptr, "threshold", 0, NULL, ICON_NONE); + } +} + void MESH_OT_intersect_boolean(struct wmOperatorType *ot) { static const EnumPropertyItem isect_boolean_operation_items[] = { @@ -335,6 +442,12 @@ void MESH_OT_intersect_boolean(struct wmOperatorType *ot) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem isect_boolean_solver_items[] = { + {ISECT_SOLVER_FAST, "FAST", 0, "Fast", "Faster Solver, some limitations"}, + {ISECT_SOLVER_EXACT, "EXACT", 0, "Exact", "Exact Solver, slower, handles more cases"}, + {0, NULL, 0, NULL, NULL}, + }; + /* identifiers */ ot->name = "Intersect (Boolean)"; ot->description = "Cut solid geometry from selected to unselected"; @@ -343,21 +456,29 @@ void MESH_OT_intersect_boolean(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_intersect_boolean_exec; ot->poll = ED_operator_editmesh; + ot->ui = edbm_intersect_boolean_ui; /* props */ RNA_def_enum(ot->srna, "operation", isect_boolean_operation_items, BMESH_ISECT_BOOLEAN_DIFFERENCE, - "Boolean", - ""); + "Boolean operation", + "Which boolean operation to apply"); RNA_def_boolean(ot->srna, "use_swap", false, "Swap", "Use with difference intersection to swap which side is kept"); + RNA_def_boolean(ot->srna, "use_self", false, "Self", "Do self-union or self-intersection"); RNA_def_float_distance( ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001); + RNA_def_enum(ot->srna, + "solver", + isect_boolean_solver_items, + ISECT_SOLVER_EXACT, + "Solver", + "Which Boolean solver to use"); /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 6f4f75e802a..6facee77c1e 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1051,7 +1051,7 @@ static void knife_init_colors(KnifeColors *colors) static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg) { const KnifeTool_OpData *kcd = arg; - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_matrix_push_projection(); GPU_polygon_offset(1.0f, 1.0f); @@ -1128,9 +1128,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v int i, snapped_verts_count, other_verts_count; float fcol[4]; - GPU_blend(true); - GPU_blend_set_func_separate( - GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(GPU_BLEND_ALPHA); GPUVertBuf *vert = GPU_vertbuf_create_with_format(format); GPU_vertbuf_data_alloc(vert, kcd->totlinehit); @@ -1147,16 +1145,13 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO); GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); - GPU_batch_bind(batch); /* draw any snapped verts first */ rgba_uchar_to_float(fcol, kcd->colors.point_a); GPU_batch_uniform_4fv(batch, "color", fcol); - GPU_matrix_bind(batch->interface); - GPU_shader_set_srgb_uniform(batch->interface); GPU_point_size(11); if (snapped_verts_count > 0) { - GPU_batch_draw_advanced(batch, 0, snapped_verts_count, 0, 0); + GPU_batch_draw_range(batch, 0, snapped_verts_count); } /* now draw the rest */ @@ -1164,13 +1159,12 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v GPU_batch_uniform_4fv(batch, "color", fcol); GPU_point_size(7); if (other_verts_count > 0) { - GPU_batch_draw_advanced(batch, snapped_verts_count, other_verts_count, 0, 0); + GPU_batch_draw_range(batch, snapped_verts_count, other_verts_count); } - GPU_batch_program_use_end(batch); GPU_batch_discard(batch); - GPU_blend(false); + GPU_blend(GPU_BLEND_NONE); } if (kcd->totkedge > 0) { @@ -1228,7 +1222,7 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v GPU_matrix_pop_projection(); /* Reset default */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } /** diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 8eeba5007e1..34fcee779de 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -354,10 +354,6 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) if (ob->mode == OB_MODE_SCULPT) { ED_sculpt_undo_geometry_begin(ob, "mask slice"); - /* TODO: The ideal functionality would be to preserve the current face sets and add a new one - * for the new triangles, but this data-layer needs to be rebuild in order to make sculpt mode - * not crash when modifying the geometry. */ - CustomData_free_layers(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly); } BMesh *bm; @@ -429,14 +425,14 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) BKE_mesh_calc_normals(ob->data); if (ob->mode == OB_MODE_SCULPT) { - ED_sculpt_undo_geometry_end(ob); SculptSession *ss = ob->sculpt; - /* Rebuild a new valid Face Set layer for the object. */ - ss->face_sets = CustomData_add_layer( - &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, mesh->totpoly); - for (int i = 0; i < mesh->totpoly; i++) { - ss->face_sets[i] = 1; + ss->face_sets = CustomData_get_layer(&((Mesh *)ob->data)->pdata, CD_SCULPT_FACE_SETS); + if (ss->face_sets) { + /* Assign a new Face Set ID to the new faces created by the slice operation. */ + const int next_face_set_id = ED_sculpt_face_sets_find_next_available_id(ob->data); + ED_sculpt_face_sets_initialize_none_to_id(ob->data, next_face_set_id); } + ED_sculpt_undo_geometry_end(ob); } BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); diff --git a/source/blender/editors/mesh/editmesh_preselect_edgering.c b/source/blender/editors/mesh/editmesh_preselect_edgering.c index d9bd63ef35f..aa1df3d76fc 100644 --- a/source/blender/editors/mesh/editmesh_preselect_edgering.c +++ b/source/blender/editors/mesh/editmesh_preselect_edgering.c @@ -159,7 +159,7 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl return; } - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_matrix_push(); GPU_matrix_mul(matrix); @@ -197,7 +197,7 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl GPU_matrix_pop(); /* Reset default */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } static void view3d_preselect_mesh_edgering_update_verts_from_edge( diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c index d53a1e2b55c..dfd646c767f 100644 --- a/source/blender/editors/mesh/editmesh_preselect_elem.c +++ b/source/blender/editors/mesh/editmesh_preselect_elem.c @@ -133,7 +133,7 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr return; } - GPU_depth_test(false); + GPU_depth_test(GPU_DEPTH_NONE); GPU_matrix_push(); GPU_matrix_mul(matrix); @@ -204,7 +204,7 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr GPU_matrix_pop(); /* Reset default */ - GPU_depth_test(true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } static void view3d_preselect_mesh_elem_update_from_vert(struct EditMesh_PreSelElem *psel, diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index d2e9b57e950..52c109b3854 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -110,7 +110,7 @@ void EDBM_select_mirrored(BMEditMesh *em, } } - EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology); + EDBM_verts_mirror_cache_begin(em, axis, true, true, false, use_topology); if (!extend) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); @@ -1423,15 +1423,13 @@ void MESH_OT_select_mode(wmOperatorType *ot) static void walker_select_count(BMEditMesh *em, int walkercode, void *start, - const bool select, - const bool select_mix, - int *r_totsel, - int *r_totunsel) + int r_count_by_select[2]) { BMesh *bm = em->bm; BMElem *ele; BMWalker walker; - int tot[2] = {0, 0}; + + r_count_by_select[0] = r_count_by_select[1] = 0; BMW_init(&walker, bm, @@ -1443,17 +1441,15 @@ static void walker_select_count(BMEditMesh *em, BMW_NIL_LAY); for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) { - tot[(BM_elem_flag_test_bool(ele, BM_ELEM_SELECT) != select)] += 1; + r_count_by_select[BM_elem_flag_test(ele, BM_ELEM_SELECT) ? 1 : 0] += 1; - if (!select_mix && tot[0] && tot[1]) { - tot[0] = tot[1] = -1; + /* Early exit when mixed (could be optional if needed. */ + if (r_count_by_select[0] && r_count_by_select[1]) { + r_count_by_select[0] = r_count_by_select[1] = -1; break; } } - *r_totsel = tot[0]; - *r_totunsel = tot[1]; - BMW_end(&walker); } @@ -1590,18 +1586,18 @@ static void mouse_mesh_loop_edge( { bool edge_boundary = false; - /* cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY */ + /* Cycle between BMW_EDGELOOP / BMW_EDGEBOUNDARY. */ if (select_cycle && BM_edge_is_boundary(eed)) { - int tot[2]; + int count_by_select[2]; - /* if the loops selected toggle the boundaries */ - walker_select_count(em, BMW_EDGELOOP, eed, select, false, &tot[0], &tot[1]); - if (tot[select] == 0) { + /* If the loops selected toggle the boundaries. */ + walker_select_count(em, BMW_EDGELOOP, eed, count_by_select); + if (count_by_select[!select] == 0) { edge_boundary = true; - /* if the boundaries selected, toggle back to the loop */ - walker_select_count(em, BMW_EDGEBOUNDARY, eed, select, false, &tot[0], &tot[1]); - if (tot[select] == 0) { + /* If the boundaries selected, toggle back to the loop. */ + walker_select_count(em, BMW_EDGEBOUNDARY, eed, count_by_select); + if (count_by_select[!select] == 0) { edge_boundary = false; } } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 1e4144db47e..4e1a56b3b55 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -2513,7 +2513,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) /* mirror before smooth */ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) { - EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology); + EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology); } /* if there is a mirror modifier with clipping, flag the verts that @@ -2658,7 +2658,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) /* Mirror before smooth. */ if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) { - EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology); + EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology); } bool failed_repeat_loop = false; @@ -7600,7 +7600,7 @@ static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op) BMVert *v; int i; - EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, use_topology, thresh, index); + EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, false, use_topology, thresh, index); BM_mesh_elem_table_ensure(bm, BM_VERT); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 46c63d2e057..a90c8dea87b 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -523,7 +523,7 @@ void EDBM_flag_enable_all(BMEditMesh *em, const char hflag) * \{ */ /** - * Return a new UVVertMap from the editmesh + * Return a new #UvVertMap from the edit-mesh. */ UvVertMap *BM_uv_vert_map_create(BMesh *bm, const bool use_select, const bool use_winding) { @@ -1059,6 +1059,7 @@ static BMVert *cache_mirr_intptr_as_bmvert(const intptr_t *index_lookup, int ind * \param em: Editmesh. * \param use_self: Allow a vertex to point to its self (middle verts). * \param use_select: Restrict to selected verts. + * \param respecthide: Skip hidden vertices. * \param use_topology: Use topology mirror. * \param maxdist: Distance for close point test. * \param r_index: Optional array to write into, as an alternative to a customdata layer @@ -1068,6 +1069,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool use_self, const bool use_select, + const bool respecthide, /* extra args */ const bool use_topology, float maxdist, @@ -1110,6 +1112,10 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, else { tree = BLI_kdtree_3d_new(bm->totvert); BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + continue; + } + BLI_kdtree_3d_insert(tree, i, v->co); } BLI_kdtree_3d_balance(tree); @@ -1118,44 +1124,45 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, #define VERT_INTPTR(_v, _i) (r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset)) BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - BLI_assert(BM_elem_index_get(v) == i); + if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + continue; + } - /* temporary for testing, check for selection */ if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) { - /* do nothing */ + continue; } - else { - BMVert *v_mirr; - int *idx = VERT_INTPTR(v, i); - if (use_topology) { - v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i); - } - else { - int i_mirr; - float co[3]; - copy_v3_v3(co, v->co); - co[axis] *= -1.0f; - - v_mirr = NULL; - i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL); - if (i_mirr != -1) { - BMVert *v_test = BM_vert_at_index(bm, i_mirr); - if (len_squared_v3v3(co, v_test->co) < maxdist_sq) { - v_mirr = v_test; - } + BLI_assert(BM_elem_index_get(v) == i); + BMVert *v_mirr; + int *idx = VERT_INTPTR(v, i); + + if (use_topology) { + v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i); + } + else { + int i_mirr; + float co[3]; + copy_v3_v3(co, v->co); + co[axis] *= -1.0f; + + v_mirr = NULL; + i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL); + if (i_mirr != -1) { + BMVert *v_test = BM_vert_at_index(bm, i_mirr); + if (len_squared_v3v3(co, v_test->co) < maxdist_sq) { + v_mirr = v_test; } } + } - if (v_mirr && (use_self || (v_mirr != v))) { - const int i_mirr = BM_elem_index_get(v_mirr); - *idx = i_mirr; - idx = VERT_INTPTR(v_mirr, i_mirr); - *idx = i; - } - else { - *idx = -1; - } + if (v_mirr && (use_self || (v_mirr != v))) { + const int i_mirr = BM_elem_index_get(v_mirr); + *idx = i_mirr; + idx = VERT_INTPTR(v_mirr, i_mirr); + *idx = i; + } + else { + *idx = -1; } } @@ -1173,12 +1180,14 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const int axis, const bool use_self, const bool use_select, + const bool respecthide, const bool use_topology) { EDBM_verts_mirror_cache_begin_ex(em, axis, use_self, use_select, + respecthide, /* extra args */ use_topology, BM_SEARCH_MAXDIST_MIRR, diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index f608e5ce6a5..22ea222cf01 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -1014,6 +1014,10 @@ static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperato Mesh *me = ED_mesh_context(C); if (BKE_mesh_has_custom_loop_normals(me)) { + BMEditMesh *em = me->edit_mesh; + if (em != NULL && em->bm->lnor_spacearr != NULL) { + BKE_lnor_spacearr_clear(em->bm->lnor_spacearr); + } return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL); } return OPERATOR_CANCELLED; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 5278da67777..bd14919d1d7 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -590,8 +590,9 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) loopofs = 0; polyofs = 0; - /* inverse transform for all selected meshes in this object */ - invert_m4_m4(imat, ob->obmat); + /* Inverse transform for all selected meshes in this object, + * See #object_join_exec for detailed comment on why the safe version is used. */ + invert_m4_m4_safe_ortho(imat, ob->obmat); /* Add back active mesh first. * This allows to keep things similar as they were, as much as possible @@ -741,6 +742,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); return OPERATOR_FINISHED; } |