diff options
author | YimingWu <xp8110@outlook.com> | 2019-10-24 15:36:28 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2019-10-24 15:36:28 +0300 |
commit | e910924b37a3fdffeb38ac14c656c16f107a9c0d (patch) | |
tree | ab626478bbb650837fd54140cfbb30a04edb6a26 /source/blender/editors/mesh | |
parent | f60406ff257c3309418413b5af76373010fb2a6f (diff) | |
parent | 42eef8f81a6aea27094985347ab802dc6bb91a61 (diff) |
Merge remote-tracking branch 'origin/master' into soc-2019-npr
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r-- | source/blender/editors/mesh/editmesh_bevel.c | 3 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_bisect.c | 2 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c | 1 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_intersect.c | 32 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife.c | 6 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife_project.c | 20 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_loopcut.c | 1 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_mask_extract.c | 24 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 6 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 202 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_data.c | 141 | ||||
-rw-r--r-- | source/blender/editors/mesh/meshtools.c | 38 |
12 files changed, 287 insertions, 189 deletions
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index b4ef2620895..7afd72f33c9 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -148,9 +148,10 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op) BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%.1f%%", RNA_float_get(op->ptr, "offset_pct")); } else { + double offset_val = (double)RNA_float_get(op->ptr, "offset"); bUnit_AsString2(offset_str, NUM_STR_REP_LEN, - (double)RNA_float_get(op->ptr, "offset"), + offset_val * sce->unit.scale_length, 3, B_UNIT_LENGTH, &sce->unit, diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 283e147b77b..4a511bbb5a2 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -455,7 +455,7 @@ void MESH_OT_bisect(struct wmOperatorType *ot) 0.00001, 0.1); - WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT); + WM_operator_properties_gesture_straightline(ot, WM_CURSOR_EDIT); #ifdef USE_GIZMO WM_gizmogrouptype_append(MESH_GGT_bisect); diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index 7155348fed5..993898bddd5 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -522,7 +522,6 @@ typedef struct GizmoGroupData_SpinRedo { PropertyRNA *prop_axis_no; PropertyRNA *prop_angle; - float rotate_axis[3]; #ifdef USE_ANGLE_Z_ORIENT /* Apply 'orient_mat' for the final value. */ float orient_axis_relative[3]; diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 370cc6a2a6d..ec740447f93 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -101,17 +101,19 @@ static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data)) /** * Use for intersect and boolean. */ -static void edbm_intersect_select(BMEditMesh *em) +static void edbm_intersect_select(BMEditMesh *em, bool do_select) { - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + if (do_select) { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); - if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { - BMIter iter; - BMEdge *e; + if (em->bm->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { + BMIter iter; + BMEdge *e; - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - BM_edge_select_set(em->bm, e, true); + BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BM_edge_select_set(em->bm, e, true); + } } } } @@ -210,10 +212,9 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op) em->bm, BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT)); } - if (has_isect) { - edbm_intersect_select(em); - } - else { + edbm_intersect_select(em, has_isect); + + if (!has_isect) { isect_len++; } } @@ -317,10 +318,9 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op) boolean_operation, eps); - if (has_isect) { - edbm_intersect_select(em); - } - else { + edbm_intersect_select(em, has_isect); + + if (!has_isect) { isect_len++; } } diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 61f9dc43c0f..395c614f328 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2777,7 +2777,7 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) op->flag |= OP_IS_MODAL_CURSOR_REGION; /* add a modal handler for this operator - handles loop selection */ - WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR); + WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_KNIFE); WM_event_add_modal_handler(C, op); knifetool_update_mval_i(kcd, event->mval); @@ -2804,8 +2804,8 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf) static const EnumPropertyItem modal_items[] = { {KNF_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, {KNF_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap To Midpoints On", ""}, - {KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap To Midpoints Off", ""}, + {KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap to Midpoints On", ""}, + {KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap to Midpoints Off", ""}, {KNF_MODEL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""}, {KNF_MODEL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""}, {KNF_MODAL_ANGLE_SNAP_TOGGLE, "ANGLE_SNAP_TOGGLE", 0, "Toggle Angle Snapping", ""}, diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index 3d34a4ad3b5..a709bd010aa 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -22,6 +22,7 @@ */ #include "DNA_curve_types.h" +#include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "BLI_math.h" @@ -142,10 +143,21 @@ static int knifeproject_exec(bContext *C, wmOperator *op) /* select only tagged faces */ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); - /* not essential, but switch out of vertex mode since the - * selected regions wont be nicely isolated after flushing. - * note: call after de-select to avoid selection flushing */ - EDBM_selectmode_disable(scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { + if (ob->type == OB_MESH) { + Mesh *me = (Mesh *)ob->data; + BMEditMesh *embm = me->edit_mesh; + if (embm) { + /* not essential, but switch out of vertex mode since the + * selected regions wont be nicely isolated after flushing. + * note: call after de-select to avoid selection flushing. + * note: do this on all participating meshes so this is in sync + * e.g. for later selection picking, see T68852.*/ + EDBM_selectmode_disable(scene, embm, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); + } + } + } + CTX_DATA_END; BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 3be94cf99c1..3c3e91e8afe 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -386,7 +386,6 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) bool ok = true; if (is_interactive == false) { if (exec_data.base_index >= bases_len) { - return OPERATOR_CANCELLED; ok = false; } else { diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 6d51e1d3393..8d98a3bf231 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -101,16 +101,21 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op) BMIter face_iter; /* Delete all unmasked faces */ + const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); + BLI_assert(cd_vert_mask_offset != -1); BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); float mask_threshold = RNA_float_get(op->ptr, "mask_threshold"); BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - bool delete_face = false; + bool keep_face = true; BM_ITER_ELEM (v, &face_iter, f, BM_VERTS_OF_FACE) { - float mask = BM_elem_float_data_get(&bm->vdata, v, CD_PAINT_MASK); - delete_face = mask < mask_threshold; + const float mask = BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); + if (mask < mask_threshold) { + keep_face = false; + break; + } } - BM_elem_flag_set(f, BM_ELEM_TAG, delete_face); + BM_elem_flag_set(f, BM_ELEM_TAG, !keep_face); } BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES); @@ -173,15 +178,16 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op) } BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); - BKE_editmesh_free_derivedmesh(em); BKE_mesh_free(new_mesh); new_mesh = BKE_mesh_from_bmesh_nomain(bm, (&(struct BMeshToMeshParams){ .calc_object_remap = false, - })); + }), + mesh); - BM_mesh_free(bm); + BKE_editmesh_free(em); + MEM_freeN(em); if (new_mesh->totvert == 0) { BKE_mesh_free(new_mesh); @@ -195,8 +201,6 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op) Object *new_ob = ED_object_add_type(C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits); BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob, &CD_MASK_EVERYTHING, true); - BKE_mesh_free(new_mesh); - if (RNA_boolean_get(op->ptr, "apply_shrinkwrap")) { BKE_shrinkwrap_mesh_nearest_surface_deform(C, new_ob, ob); } @@ -211,6 +215,8 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op) } } + BKE_mesh_calc_normals(new_ob->data); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, new_ob); BKE_mesh_batch_cache_dirty_tag(new_ob->data, BKE_MESH_BATCH_DIRTY_ALL); DEG_relations_tag_update(bmain); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index cad9e9a3d06..3e59a884696 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2642,8 +2642,9 @@ bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len) bool EDBM_mesh_deselect_all_multi(struct bContext *C) { + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ViewContext vc; - ED_view3d_viewcontext_init(C, &vc); + ED_view3d_viewcontext_init(C, &vc, depsgraph); uint bases_len = 0; Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( vc.view_layer, vc.v3d, &bases_len); @@ -4219,7 +4220,8 @@ void MESH_OT_select_nth(wmOperatorType *ot) void em_setup_viewcontext(bContext *C, ViewContext *vc) { - ED_view3d_viewcontext_init(C, vc); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ED_view3d_viewcontext_init(C, vc, depsgraph); if (vc->obedit) { vc->em = BKE_editmesh_from_object(vc->obedit); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 0c4db012786..a20ae5fc1ac 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3161,7 +3161,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) } MEM_freeN(objects); - BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count_multi); + BKE_reportf(op->reports, RPT_INFO, "Removed %d vertice(s)", count_multi); return OPERATOR_FINISHED; } @@ -3872,7 +3872,7 @@ void MESH_OT_knife_cut(wmOperatorType *ot) /* internal */ RNA_def_int( - ot->srna, "cursor", BC_KNIFECURSOR, 0, BC_NUMCURSORS, "Cursor", "", 0, BC_NUMCURSORS); + ot->srna, "cursor", WM_CURSOR_KNIFE, 0, WM_CURSOR_NUM, "Cursor", "", 0, WM_CURSOR_NUM); } /** \} */ @@ -3946,6 +3946,61 @@ static Base *mesh_separate_tagged( return base_new; } +static Base *mesh_separate_arrays(Main *bmain, + Scene *scene, + ViewLayer *view_layer, + Base *base_old, + BMesh *bm_old, + BMVert **verts, + uint verts_len, + BMEdge **edges, + uint edges_len, + BMFace **faces, + uint faces_len) +{ + Base *base_new; + Object *obedit = base_old->object; + BMesh *bm_new; + + bm_new = BM_mesh_create(&bm_mesh_allocsize_default, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + + CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0); + CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0); + CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0); + CustomData_copy(&bm_old->pdata, &bm_new->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0); + + CustomData_bmesh_init_pool(&bm_new->vdata, verts_len, BM_VERT); + CustomData_bmesh_init_pool(&bm_new->edata, edges_len, BM_EDGE); + CustomData_bmesh_init_pool(&bm_new->ldata, faces_len * 3, BM_LOOP); + CustomData_bmesh_init_pool(&bm_new->pdata, faces_len, BM_FACE); + + base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, USER_DUP_MESH); + + /* normally would call directly after but in this case delay recalc */ + /* DAG_relations_tag_update(bmain); */ + + /* new in 2.5 */ + assign_matarar(bmain, base_new->object, give_matarar(obedit), *give_totcolp(obedit)); + + ED_object_base_select(base_new, BA_SELECT); + + BM_mesh_copy_arrays(bm_old, bm_new, verts, verts_len, edges, edges_len, faces, faces_len); + + for (uint i = 0; i < verts_len; i++) { + BM_vert_kill(bm_old, verts[i]); + } + + BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0})); + + BM_mesh_free(bm_new); + ((Mesh *)base_new->object->data)->edit_mesh = NULL; + + return base_new; +} + static bool mesh_separate_selected( Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old) { @@ -3959,41 +4014,6 @@ static bool mesh_separate_selected( return (mesh_separate_tagged(bmain, scene, view_layer, base_old, bm_old) != NULL); } -/* flush a hflag to from verts to edges/faces */ -static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag) -{ - BMEdge *e; - BMLoop *l_iter; - BMLoop *l_first; - BMFace *f; - - BMIter eiter; - BMIter fiter; - - bool ok; - - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, hflag) && BM_elem_flag_test(e->v2, hflag)) { - BM_elem_flag_enable(e, hflag); - } - else { - BM_elem_flag_disable(e, hflag); - } - } - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - ok = true; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (!BM_elem_flag_test(l_iter->v, hflag)) { - ok = false; - break; - } - } while ((l_iter = l_iter->next) != l_first); - - BM_elem_flag_set(f, hflag, ok); - } -} - /** * Sets an object to a single material. from one of its slots. * @@ -4109,72 +4129,64 @@ static bool mesh_separate_material( static bool mesh_separate_loose( Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_old, BMesh *bm_old) { - int i; - BMEdge *e; - BMVert *v_seed; - BMWalker walker; - bool result = false; - int max_iter = bm_old->totvert; + /* Without this, we duplicate the object mode mesh for each loose part. + * This can get very slow especially for large meshes with many parts + * which would duplicate the mesh on entering edit-mode. */ + const bool clear_object_data = true; - /* Clear all selected vertices */ - BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + bool result = false; - /* A "while (true)" loop should work here as each iteration should - * select and remove at least one vertex and when all vertices - * are selected the loop will break out. But guard against bad - * behavior by limiting iterations to the number of vertices in the - * original mesh.*/ - for (i = 0; i < max_iter; i++) { - int tot = 0; - /* Get a seed vertex to start the walk */ - v_seed = BM_iter_at_index(bm_old, BM_VERTS_OF_MESH, NULL, 0); + BMVert **vert_groups = MEM_mallocN(sizeof(*vert_groups) * bm_old->totvert, __func__); + BMEdge **edge_groups = MEM_mallocN(sizeof(*edge_groups) * bm_old->totedge, __func__); + BMFace **face_groups = MEM_mallocN(sizeof(*face_groups) * bm_old->totface, __func__); + + int(*groups)[3] = NULL; + int groups_len = BM_mesh_calc_edge_groups_as_arrays( + bm_old, vert_groups, edge_groups, face_groups, &groups); + if (groups_len <= 1) { + goto finally; + } + + if (clear_object_data) { + ED_mesh_geometry_clear(base_old->object->data); + } + + /* Separate out all groups except the first. */ + uint group_ofs[3] = {UNPACK3(groups[0])}; + for (int i = 1; i < groups_len; i++) { + Base *base_new = mesh_separate_arrays(bmain, + scene, + view_layer, + base_old, + bm_old, + vert_groups + group_ofs[0], + groups[i][0], + edge_groups + group_ofs[1], + groups[i][1], + face_groups + group_ofs[2], + groups[i][2]); + result |= (base_new != NULL); - /* No vertices available, can't do anything */ - if (v_seed == NULL) { - break; - } + group_ofs[0] += groups[i][0]; + group_ofs[1] += groups[i][1]; + group_ofs[2] += groups[i][2]; + } - /* Select the seed explicitly, in case it has no edges */ - if (!BM_elem_flag_test(v_seed, BM_ELEM_TAG)) { - BM_elem_flag_enable(v_seed, BM_ELEM_TAG); - tot++; - } + Mesh *me_old = base_old->object->data; + BMEditMesh *em_old = me_old->edit_mesh; - /* Walk from the single vertex, selecting everything connected - * to it */ - BMW_init(&walker, - bm_old, - BMW_VERT_SHELL, - BMW_MASK_NOP, - BMW_MASK_NOP, - BMW_MASK_NOP, - BMW_FLAG_NOP, - BMW_NIL_LAY); + BM_mesh_elem_hflag_disable_all(em_old->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); - for (e = BMW_begin(&walker, v_seed); e; e = BMW_step(&walker)) { - if (!BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); - tot++; - } - if (!BM_elem_flag_test(e->v2, BM_ELEM_TAG)) { - BM_elem_flag_enable(e->v2, BM_ELEM_TAG); - tot++; - } - } - BMW_end(&walker); - - if (bm_old->totvert == tot) { - /* Every vertex selected, nothing to separate, work is done */ - break; - } + if (clear_object_data) { + BM_mesh_bm_to_me(NULL, em_old->bm, me_old, (&(struct BMeshToMeshParams){0})); + } - /* Flush the selection to get edge/face selections matching - * the vertex selection */ - bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG); +finally: + MEM_freeN(vert_groups); + MEM_freeN(edge_groups); + MEM_freeN(face_groups); - /* Move selection into a separate object */ - result |= (mesh_separate_tagged(bmain, scene, view_layer, base_old, bm_old) != NULL); - } + MEM_freeN(groups); return result; } diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 569994bead1..7007ff29401 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -880,14 +880,14 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot) void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose) { - if (calc_edges_loose && mesh->totedge) { - BKE_mesh_calc_edges_loose(mesh); - } - if (calc_edges || ((mesh->totpoly || mesh->totface) && mesh->totedge == 0)) { BKE_mesh_calc_edges(mesh, calc_edges, true); } + if (calc_edges_loose && mesh->totedge) { + BKE_mesh_calc_edges_loose(mesh); + } + /* Default state is not to have tessface's so make sure this is the case. */ BKE_mesh_tessface_clear(mesh); @@ -1023,73 +1023,104 @@ static void mesh_add_polys(Mesh *mesh, int len) mesh->totpoly = totpoly; } -static void mesh_remove_verts(Mesh *mesh, int len) +/* -------------------------------------------------------------------- */ +/** \name Add Geometry + * \{ */ + +void ED_mesh_verts_add(Mesh *mesh, ReportList *reports, int count) { - int totvert; + if (mesh->edit_mesh) { + BKE_report(reports, RPT_ERROR, "Cannot add vertices in edit mode"); + return; + } + mesh_add_verts(mesh, count); +} - if (len == 0) { +void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count) +{ + if (mesh->edit_mesh) { + BKE_report(reports, RPT_ERROR, "Cannot add edges in edit mode"); + return; + } + mesh_add_edges(mesh, count); +} + +void ED_mesh_loops_add(Mesh *mesh, ReportList *reports, int count) +{ + if (mesh->edit_mesh) { + BKE_report(reports, RPT_ERROR, "Cannot add loops in edit mode"); return; } + mesh_add_loops(mesh, count); +} - totvert = mesh->totvert - len; - CustomData_free_elem(&mesh->vdata, totvert, len); +void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count) +{ + if (mesh->edit_mesh) { + BKE_report(reports, RPT_ERROR, "Cannot add polygons in edit mode"); + return; + } + mesh_add_polys(mesh, count); +} - /* set final vertex list size */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Geometry + * \{ */ + +static void mesh_remove_verts(Mesh *mesh, int len) +{ + if (len == 0) { + return; + } + const int totvert = mesh->totvert - len; + CustomData_free_elem(&mesh->vdata, totvert, len); mesh->totvert = totvert; } static void mesh_remove_edges(Mesh *mesh, int len) { - int totedge; - if (len == 0) { return; } - - totedge = mesh->totedge - len; + const int totedge = mesh->totedge - len; CustomData_free_elem(&mesh->edata, totedge, len); - mesh->totedge = totedge; } -#if 0 -void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces) +static void mesh_remove_loops(Mesh *mesh, int len) { - if (mesh->edit_mesh) { - BKE_report(reports, RPT_ERROR, "Cannot add geometry in edit mode"); + if (len == 0) { return; } - - if (verts) { - mesh_add_verts(mesh, verts); - } - if (edges) { - mesh_add_edges(mesh, edges); - } - if (faces) { - mesh_add_faces(mesh, faces); - } + const int totloop = mesh->totloop - len; + CustomData_free_elem(&mesh->ldata, totloop, len); + mesh->totloop = totloop; } -#endif -void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count) +static void mesh_remove_polys(Mesh *mesh, int len) { - if (mesh->edit_mesh) { - BKE_report(reports, RPT_ERROR, "Cannot add edges in edit mode"); + if (len == 0) { return; } - - mesh_add_edges(mesh, count); + const int totpoly = mesh->totpoly - len; + CustomData_free_elem(&mesh->pdata, totpoly, len); + mesh->totpoly = totpoly; } -void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count) +void ED_mesh_verts_remove(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_mesh) { - BKE_report(reports, RPT_ERROR, "Cannot add vertices in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot remove vertices in edit mode"); + return; + } + else if (count > mesh->totvert) { + BKE_report(reports, RPT_ERROR, "Cannot remove more vertices than the mesh contains"); return; } - mesh_add_verts(mesh, count); + mesh_remove_verts(mesh, count); } void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count) @@ -1106,40 +1137,44 @@ void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count) mesh_remove_edges(mesh, count); } -void ED_mesh_vertices_remove(Mesh *mesh, ReportList *reports, int count) +void ED_mesh_loops_remove(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_mesh) { - BKE_report(reports, RPT_ERROR, "Cannot remove vertices in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot remove loops in edit mode"); return; } - else if (count > mesh->totvert) { - BKE_report(reports, RPT_ERROR, "Cannot remove more vertices than the mesh contains"); + else if (count > mesh->totloop) { + BKE_report(reports, RPT_ERROR, "Cannot remove more loops than the mesh contains"); return; } - mesh_remove_verts(mesh, count); + mesh_remove_loops(mesh, count); } -void ED_mesh_loops_add(Mesh *mesh, ReportList *reports, int count) +void ED_mesh_polys_remove(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_mesh) { - BKE_report(reports, RPT_ERROR, "Cannot add loops in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot remove polys in edit mode"); + return; + } + else if (count > mesh->totpoly) { + BKE_report(reports, RPT_ERROR, "Cannot remove more polys than the mesh contains"); return; } - mesh_add_loops(mesh, count); + mesh_remove_polys(mesh, count); } -void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count) +void ED_mesh_geometry_clear(Mesh *mesh) { - if (mesh->edit_mesh) { - BKE_report(reports, RPT_ERROR, "Cannot add polygons in edit mode"); - return; - } - - mesh_add_polys(mesh, count); + mesh_remove_verts(mesh, mesh->totvert); + mesh_remove_edges(mesh, mesh->totedge); + mesh_remove_loops(mesh, mesh->totloop); + mesh_remove_polys(mesh, mesh->totpoly); } +/** \} */ + void ED_mesh_report_mirror_ex(wmOperator *op, int totmirr, int totfail, char selectmode) { const char *elem_type; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index c68f5963cbd..a918996563f 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -54,6 +54,7 @@ #include "BKE_multires.h" #include "BKE_object.h" #include "BKE_object_deform.h" +#include "BKE_object_facemap.h" #include "BKE_report.h" #include "DEG_depsgraph.h" @@ -267,6 +268,22 @@ static void join_mesh_single(Depsgraph *depsgraph, mpoly->loopstart += *loopofs; mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0; } + + /* Face maps. */ + int *fmap = CustomData_get(pdata, *polyofs, CD_FACEMAP); + int *fmap_src = CustomData_get(&me->pdata, 0, CD_FACEMAP); + + /* Remap to correct new face-map indices, if needed. */ + if (fmap_src) { + BLI_assert(fmap != NULL); + int *fmap_index_map; + int fmap_index_map_len; + fmap_index_map = BKE_object_facemap_index_map_create(ob_src, ob_dst, &fmap_index_map_len); + BKE_object_facemap_index_map_apply(fmap, me->totpoly, fmap_index_map, fmap_index_map_len); + if (fmap_index_map != NULL) { + MEM_freeN(fmap_index_map); + } + } } /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */ @@ -403,7 +420,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) key->type = KEY_RELATIVE; } - /* first pass over objects - copying materials and vertexgroups across */ + /* First pass over objects: Copying materials, vertex-groups & face-maps across. */ CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) { /* only act if a mesh, and not the one we're joining to */ if ((ob != ob_iter) && (ob_iter->type == OB_MESH)) { @@ -422,6 +439,19 @@ int join_mesh_exec(bContext *C, wmOperator *op) ob->actdef = 1; } + /* Join this object's face maps to the base one's. */ + for (bFaceMap *fmap = ob_iter->fmaps.first; fmap; fmap = fmap->next) { + /* See if this group exists in the object (if it doesn't, add it to the end) */ + if (BKE_object_facemap_find_name(ob, fmap->name) == NULL) { + bFaceMap *fmap_new = MEM_callocN(sizeof(bFaceMap), "join faceMap"); + memcpy(fmap_new, fmap, sizeof(bFaceMap)); + BLI_addtail(&ob->fmaps, fmap_new); + } + } + if (ob->fmaps.first && ob->actfmap == 0) { + ob->actfmap = 1; + } + if (me->totvert) { /* Add this object's materials to the base one's if they don't exist already * (but only if limits not exceeded yet) */ @@ -1110,7 +1140,8 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, return false; } - ED_view3d_viewcontext_init(C, &vc); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ED_view3d_viewcontext_init(C, &vc, depsgraph); ED_view3d_select_id_validate(&vc); if (dist_px) { @@ -1291,7 +1322,8 @@ bool ED_mesh_pick_vert( return false; } - ED_view3d_viewcontext_init(C, &vc); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ED_view3d_viewcontext_init(C, &vc, depsgraph); ED_view3d_select_id_validate(&vc); if (use_zbuf) { |