diff options
Diffstat (limited to 'source/blender/editors/mesh')
18 files changed, 195 insertions, 202 deletions
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index b7ee50a9461..648008a4779 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -65,7 +65,7 @@ void paintface_flush_flags(struct bContext *C, Object *ob, short flag) return; } - /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */ + /* NOTE: call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags. */ /* we could call this directly in all areas that change selection, * since this could become slow for realtime updates (circle-select for eg) */ @@ -433,7 +433,7 @@ bool paintface_mouse_select( /* image window redraw */ paintface_flush_flags(C, ob, SELECT); - ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */ + ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */ return true; } diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 110f1975d8d..01736f2919a 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -279,7 +279,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) for (int i = 0; i < NUM_VALUE_KINDS; i++) { opdata->shift_value[i] = -1.0f; opdata->initial_length[i] = -1.0f; - /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */ + /* NOTE: scale for #OFFSET_VALUE will get overwritten in #edbm_bevel_invoke. */ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch; initNumInput(&opdata->num_input[i]); @@ -347,7 +347,7 @@ static bool edbm_bevel_calc(wmOperator *op) /* revert to original mesh */ if (opdata->is_modal) { - EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false); + EDBM_redo_state_restore(&opdata->ob_store[ob_index].mesh_backup, em, false); } const int material = CLAMPIS(material_init, -1, obedit->totcol - 1); @@ -436,7 +436,7 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false); + EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup); } ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); if (v3d) { @@ -456,7 +456,7 @@ static void edbm_bevel_cancel(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { Object *obedit = opdata->ob_store[ob_index].ob; BMEditMesh *em = BKE_editmesh_from_object(obedit); - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, em, true); + EDBM_redo_state_restore_and_free(&opdata->ob_store[ob_index].mesh_backup, em, true); EDBM_update(obedit->data, &(const struct EDBMUpdate_Params){ .calc_looptri = false, diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 42cf36dda81..3c8afe8e7db 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -67,7 +67,7 @@ typedef struct { /* Aligned with objects array. */ struct { - BMBackup mesh; + BMBackup mesh_backup; bool is_valid; bool is_dirty; } * backup; @@ -160,7 +160,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (em->bm->totedgesel != 0) { opdata->backup[ob_index].is_valid = true; - opdata->backup[ob_index].mesh = EDBM_redo_state_store(em); + opdata->backup[ob_index].mesh_backup = EDBM_redo_state_store(em); } } @@ -184,7 +184,7 @@ static void edbm_bisect_exit(bContext *C, BisectData *opdata) for (int ob_index = 0; ob_index < opdata->backup_len; ob_index++) { if (opdata->backup[ob_index].is_valid) { - EDBM_redo_state_free(&opdata->backup[ob_index].mesh, NULL, false); + EDBM_redo_state_free(&opdata->backup[ob_index].mesh_backup); } } MEM_freeN(opdata->backup); @@ -280,7 +280,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) /* -------------------------------------------------------------------- */ /* Modal support */ - /* Note: keep this isolated, exec can work without this */ + /* NOTE: keep this isolated, exec can work without this. */ if (opdata != NULL) { mesh_bisect_interactive_calc(C, op, plane_co, plane_no); /* Write back to the props. */ @@ -301,7 +301,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) if (opdata != NULL) { if (opdata->backup[ob_index].is_dirty) { - EDBM_redo_state_restore(opdata->backup[ob_index].mesh, em, false); + EDBM_redo_state_restore(&opdata->backup[ob_index].mesh_backup, em, false); opdata->backup[ob_index].is_dirty = false; } } diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index 1c27ab00715..18f51ae9df2 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -209,7 +209,7 @@ static void edbm_inset_exit(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false); + EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup); } ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); if (v3d) { @@ -235,7 +235,7 @@ static void edbm_inset_cancel(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { Object *obedit = opdata->ob_store[ob_index].ob; BMEditMesh *em = BKE_editmesh_from_object(obedit); - EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, em, true); + EDBM_redo_state_restore_and_free(&opdata->ob_store[ob_index].mesh_backup, em, true); EDBM_update(obedit->data, &(const struct EDBMUpdate_Params){ .calc_looptri = false, @@ -276,7 +276,7 @@ static bool edbm_inset_calc(wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); if (opdata->is_modal) { - EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false); + EDBM_redo_state_restore(&opdata->ob_store[ob_index].mesh_backup, em, false); } if (use_individual) { diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 0e2dd492e06..73f6a3f3238 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -157,7 +157,7 @@ typedef struct KnifePosData { typedef struct KnifeTool_OpData { ARegion *region; /* region that knifetool was activated in */ void *draw_handle; /* for drawing preview loop */ - ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */ + ViewContext vc; /* NOTE: _don't_ use 'mval', instead use the one we define below. */ float mval[2]; /* mouse value with snapping applied */ // bContext *C; @@ -1475,7 +1475,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd) } } - /* Note: as following loop progresses, the 'v' fields of + /* NOTE: as following loop progresses, the 'v' fields of * the linehits will be filled in (as edges are split or * in-face verts are made), so it may be true that both * the v and the kfe or f fields will be non-NULL. */ @@ -1760,7 +1760,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd, if (RV3D_CLIPPING_ENABLED(kcd->vc.v3d, kcd->vc.rv3d)) { float view_clip[2][3]; - /* note: view_clip[0] should never get clipped */ + /* NOTE: view_clip[0] should never get clipped. */ copy_v3_v3(view_clip[0], p_ofs); madd_v3_v3v3fl(view_clip[1], p_ofs, view, dist); diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index aa144dd3f3c..09b17acf56d 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -30,6 +30,7 @@ #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" @@ -59,7 +60,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ARegion *region = CTX_wm_region(C); - struct Mesh *me_eval; + const struct Mesh *me_eval; bool me_eval_needs_free; if (ob->type == OB_MESH || ob->runtime.data_eval) { @@ -113,7 +114,7 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C, BKE_nurbList_free(&nurbslist); if (me_eval_needs_free) { - BKE_mesh_free(me_eval); + BKE_mesh_free((struct Mesh *)me_eval); } } diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 71319338a53..0a4fecde6ea 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -241,7 +241,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) * in editmesh_select.c (around line 1000)... */ /* sets as active, useful for other tools */ if (em->selectmode & SCE_SELECT_VERTEX) { - /* low priority TODO, get vertrex close to mouse */ + /* low priority TODO: get vertrex close to mouse. */ BM_select_history_store(em->bm, lcd->eed->v1); } if (em->selectmode & SCE_SELECT_EDGE) { diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 993905462db..cccfc7e934c 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -126,7 +126,7 @@ static int geometry_extract_apply(bContext *C, .calc_face_normal = true, })); - BMEditMesh *em = BKE_editmesh_create(bm, false); + BMEditMesh *em = BKE_editmesh_create(bm); /* Generate the tags for deleting geometry in the extracted object. */ tag_fn(bm, params); @@ -206,7 +206,7 @@ static int geometry_extract_apply(bContext *C, }), mesh); - BKE_editmesh_free(em); + BKE_editmesh_free_data(em); MEM_freeN(em); if (new_mesh->totvert == 0) { diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index 593545ddcef..30a453a32ee 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -29,6 +29,7 @@ #include "DNA_windowmanager_types.h" #ifdef WITH_FREESTYLE +# include "BKE_customdata.h" # include "DNA_meshdata_types.h" #endif diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 8626520ec37..5a2a090b725 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -927,7 +927,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed /* single edge, extend */ if (i == 1 && e_best->l) { - /* note: if the case of 3 edges has one change in loop stepping, + /* NOTE: if the case of 3 edges has one change in loop stepping, * if this becomes more involved we may be better off splitting * the 3 edge case into its own else-if branch */ if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) { @@ -975,7 +975,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed BM_mesh_edgesplit(em->bm, true, true, true); - /* note: the output of the bmesh operator is ignored, since we built + /* NOTE: the output of the bmesh operator is ignored, since we built * the contiguous loop pairs to split already, its possible that some * edge did not split even though it was tagged which would not work * as expected (but not crash), however there are checks to ensure diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index d8973e100bc..830c9abb41e 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -35,6 +35,8 @@ #include "BLI_utildefines_stack.h" #include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_report.h" @@ -434,7 +436,7 @@ struct NearestEdgeUserData { struct NearestEdgeUserData_Hit hit_cycle; }; -/* note; uses v3d, so needs active 3d window */ +/* NOTE: uses v3d, so needs active 3d window. */ static void find_nearest_edge__doClosest( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { @@ -964,7 +966,7 @@ static bool unified_findnearest(ViewContext *vc, } } - /* return only one of 3 pointers, for frontbuffer redraws */ + /* Return only one of 3 pointers, for front-buffer redraws. */ if (hit.v.ele) { hit.f.ele = NULL; hit.e.ele = NULL; @@ -3446,7 +3448,7 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in select_linked_delimit_begin(bm, delimit); } - /* Note: logic closely matches 'edbm_select_linked_exec', keep in sync */ + /* NOTE: logic closely matches #edbm_select_linked_exec, keep in sync. */ if (ele->head.htype == BM_VERT) { BMVert *eve = (BMVert *)ele; @@ -4739,10 +4741,11 @@ static bool edbm_select_ungrouped_poll(bContext *C) BMEditMesh *em = BKE_editmesh_from_object(obedit); const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT); + const ListBase *defbase = BKE_object_defgroup_list(obedit); if ((em->selectmode & SCE_SELECT_VERTEX) == 0) { CTX_wm_operator_poll_msg_set(C, "Must be in vertex selection mode"); } - else if (BLI_listbase_is_empty(&obedit->defbase) || cd_dvert_offset == -1) { + else if (BLI_listbase_is_empty(defbase) || cd_dvert_offset == -1) { CTX_wm_operator_poll_msg_set(C, "No weights/vertex groups on object"); } else { diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index 2ffeaa06751..c452f7a7487 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -29,6 +29,8 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_material.h" @@ -559,7 +561,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) * \{ */ /** - * Note: This is not normal, but the edge direction itself and always in + * NOTE: This is not normal, but the edge direction itself and always in * a positive quadrant (tries z, y then x). * Therefore we need to use the entire object transformation matrix. */ @@ -1041,7 +1043,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (cd_dvert_offset == -1) { continue; } - defbase_len = BLI_listbase_count(&ob->defbase); + defbase_len = BKE_object_defgroup_count(ob); if (defbase_len == 0) { continue; } @@ -1090,8 +1092,10 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) /* We store the names of the vertex groups, so we can select * vertex groups with the same name in different objects. */ + const ListBase *defbase = BKE_object_defgroup_list(ob); + int i = 0; - LISTBASE_FOREACH (bDeformGroup *, dg, &ob->defbase) { + LISTBASE_FOREACH (bDeformGroup *, dg, defbase) { if (BLI_BITMAP_TEST(defbase_selected, i)) { BLI_gset_add(gset, dg->name); } @@ -1128,7 +1132,8 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (cd_dvert_offset == -1) { continue; } - defbase_len = BLI_listbase_count(&ob->defbase); + const ListBase *defbase = BKE_object_defgroup_list(ob); + defbase_len = BLI_listbase_count(defbase); if (defbase_len == 0) { continue; } @@ -1141,7 +1146,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) GSetIterator gs_iter; GSET_ITER (gs_iter, gset) { const char *name = BLI_gsetIterator_getKey(&gs_iter); - int vgroup_id = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)); + int vgroup_id = BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name)); if (vgroup_id != -1) { BLI_BITMAP_ENABLE(defbase_selected, vgroup_id); found_any = true; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index fe9656d277e..41a9f426798 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -44,6 +44,7 @@ #include "BLI_string.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_key.h" @@ -145,7 +146,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/* Note, these values must match delete_mesh() event values */ +/* NOTE: these values must match delete_mesh() event values. */ static const EnumPropertyItem prop_mesh_cornervert_types[] = { {SUBD_CORNER_INNERVERT, "INNERVERT", 0, "Inner Vert", ""}, {SUBD_CORNER_PATH, "PATH", 0, "Path", ""}, @@ -245,7 +246,7 @@ static void mesh_operator_edgering_props(wmOperatorType *ot, const int cuts_min, const int cuts_default) { - /* Note, these values must match delete_mesh() event values */ + /* NOTE: these values must match delete_mesh() event values. */ static const EnumPropertyItem prop_subd_edgering_types[] = { {SUBD_RING_INTERP_LINEAR, "LINEAR", 0, "Linear", ""}, {SUBD_RING_INTERP_PATH, "PATH", 0, "Blend Path", ""}, @@ -431,7 +432,7 @@ void MESH_OT_unsubdivide(wmOperatorType *ot) /** \name Delete Operator * \{ */ -/* Note, these values must match delete_mesh() event values */ +/* NOTE: these values must match delete_mesh() event values. */ enum { MESH_DELETE_VERT = 0, MESH_DELETE_EDGE = 1, @@ -973,7 +974,7 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) #ifdef USE_FACE_CREATE_SEL_EXTEND /* normally we would want to leave the new geometry selected, * but being able to press F many times to add geometry is too useful! */ - if (ele_desel && (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) && + if (ele_desel && (BMO_slot_buffer_len(bmop.slots_out, "faces.out") == 1) && (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out"))) { edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face); } @@ -1264,9 +1265,12 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * } } if (checks_succeded) { + BMBackup em_backup = EDBM_redo_state_store(em); + BM_custom_loop_normals_to_vector_layer(bm); BMO_op_exec(bm, &bmop); + const bool failure = BMO_error_occurred_at_level(bm, BMO_ERROR_FATAL); len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (len && is_pair) { @@ -1275,8 +1279,14 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); } - if (!EDBM_op_finish(em, &bmop, op, true)) { + bool em_backup_free = true; + if (!EDBM_op_finish(em, &bmop, op, false)) { + len = 0; + } + else if (failure) { len = 0; + EDBM_redo_state_restore_and_free(&em_backup, em, true); + em_backup_free = false; } else { /* so newly created edges get the selection state from the vertex */ @@ -1291,6 +1301,10 @@ static bool edbm_connect_vert_pair(BMEditMesh *em, struct Mesh *me, wmOperator * .is_destructive = true, }); } + + if (em_backup_free) { + EDBM_redo_state_free(&em_backup); + } } MEM_freeN(verts); @@ -2331,7 +2345,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BMO_slot_buffer_hflag_enable( em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); - const int tot_rotate = BMO_slot_buffer_count(bmop.slots_out, "edges.out"); + const int tot_rotate = BMO_slot_buffer_len(bmop.slots_out, "edges.out"); const int tot_failed = tot - tot_rotate; tot_rotate_all += tot_rotate; @@ -3012,10 +3026,8 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, true)) { @@ -3050,13 +3062,10 @@ static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "reverse_uvs faces=%hf", BM_ELEM_SELECT); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } @@ -3091,13 +3100,10 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { continue; } @@ -3133,15 +3139,12 @@ static int edbm_reverse_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; - /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ EDBM_op_init(em, &bmop, op, "reverse_colors faces=%hf", BM_ELEM_SELECT); - /* execute the operator */ BMO_op_exec(em->bm, &bmop); - /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, true)) { - return OPERATOR_CANCELLED; + continue; } EDBM_update(obedit->data, @@ -4222,7 +4225,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) /* for ED_view3d_project_float_object */ ED_view3d_init_mats_rv3d(obedit, region->regiondata); - /* TODO, investigate using index lookup for screen_vert_coords() rather than a hash table */ + /* TODO: investigate using index lookup for #screen_vert_coords() rather than a hash table. */ /* the floating point coordinates of verts in screen space will be * stored in a hash table according to the vertices pointer */ @@ -5737,7 +5740,7 @@ static int edbm_decimate_exec(bContext *C, wmOperator *op) float *vweights = MEM_mallocN(sizeof(*vweights) * bm->totvert, __func__); { const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); - const int defbase_act = obedit->actdef - 1; + const int defbase_act = BKE_object_defgroup_active_index_get(obedit) - 1; if (use_vertex_group && (cd_dvert_offset == -1)) { BKE_report(op->reports, RPT_WARNING, "No active vertex group"); @@ -5874,7 +5877,7 @@ void MESH_OT_decimate(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* Note, keep in sync with 'rna_def_modifier_decimate' */ + /* NOTE: keep in sync with 'rna_def_modifier_decimate'. */ RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f); RNA_def_boolean(ot->srna, @@ -6558,7 +6561,7 @@ enum { typedef struct BMElemSort { /** Sort factor */ float srt; - /** Original index of this element _in its mempool_ */ + /** Original index of this element (in its #BLI_mempool). */ int org_idx; } BMElemSort; @@ -6751,7 +6754,7 @@ static void sort_bmelem_flag(bContext *C, BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) { if (BM_elem_flag_test(fa, flag)) { /* Reverse materials' order, not order of faces inside each mat! */ - /* Note: cannot use totcol, as mat_nr may sometimes be greater... */ + /* NOTE: cannot use totcol, as mat_nr may sometimes be greater... */ float srt = reverse ? (float)(MAXMAT - fa->mat_nr) : (float)fa->mat_nr; pb[i] = false; sb[affected[2]].org_idx = i; @@ -7304,7 +7307,7 @@ static int edbm_bridge_edge_loops_for_single_editmesh(wmOperator *op, BMO_op_exec(em->bm, &bmop); - if (!BMO_error_occurred(em->bm)) { + if (!BMO_error_occurred_at_level(em->bm, BMO_ERROR_CANCEL)) { /* when merge is used the edges are joined and remain selected */ if (use_merge == false) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); @@ -7670,7 +7673,7 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); /* Hull fails if input is coplanar */ - if (BMO_error_occurred(em->bm)) { + if (BMO_error_occurred_at_level(em->bm, BMO_ERROR_CANCEL)) { EDBM_op_finish(em, &bmop, op, true); continue; } @@ -8385,7 +8388,7 @@ static void point_normals_update_header(bContext *C, wmOperator *op) ED_area_status_text(CTX_wm_area(C), header); } -/* TODO move that to generic function in BMesh? */ +/* TODO: move that to generic function in BMesh? */ static void bmesh_selected_verts_center_calc(BMesh *bm, float *r_center) { BMVert *v; @@ -9691,7 +9694,7 @@ static int edbm_smooth_normals_exec(bContext *C, wmOperator *op) BKE_lnor_space_custom_data_to_normal( bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal); - /* Note: again, this is not true spherical interpolation that normals would need... + /* NOTE: again, this is not true spherical interpolation that normals would need... * But it's probably good enough for now. */ mul_v3_fl(current_normal, 1.0f - factor); mul_v3_fl(smooth_normal[i], factor); diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 112de68b52c..fc9e1aa8b1a 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -33,6 +33,7 @@ #include "BLI_listbase.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_key.h" #include "BKE_layer.h" @@ -671,7 +672,7 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * em->bm->shapenr = um->shapenr; - EDBM_mesh_free(em); + EDBM_mesh_free_data(em); bm = BM_mesh_create(&allocsize, &((struct BMeshCreateParams){ @@ -681,13 +682,21 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key * BM_mesh_bm_from_me(bm, &um->me, (&(struct BMeshFromMeshParams){ - .calc_face_normal = true, + /* Handled with tessellation. */ + .calc_face_normal = false, .active_shapekey = um->shapenr, })); - em_tmp = BKE_editmesh_create(bm, true); + em_tmp = BKE_editmesh_create(bm); *em = *em_tmp; + /* Calculate face normals and tessellation at once since it's multi-threaded. + * The vertex normals are stored in the undo-mesh, so this doesn't need to be updated. */ + BKE_editmesh_looptri_calc_ex(em, + &(const struct BMeshCalcTessellation_Params){ + .face_normals = true, + }); + em->selectmode = um->selectmode; bm->selectmode = um->selectmode; @@ -865,7 +874,7 @@ static void mesh_undosys_step_decode(struct bContext *C, BMEditMesh *em = me->edit_mesh; undomesh_to_editmesh(&elem->data, obedit, em, me->key); em->needs_flush_to_id = 1; - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY); } /* The first element is always active */ diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 141b69f0465..85c646d689c 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -68,6 +68,9 @@ * just as the undo stack would. * So leaving this as an interface for further work */ +/** + * Save a copy of the #BMesh for restoring later. + */ BMBackup EDBM_redo_state_store(BMEditMesh *em) { BMBackup backup; @@ -75,42 +78,41 @@ BMBackup EDBM_redo_state_store(BMEditMesh *em) return backup; } -void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess) +void EDBM_redo_state_restore(BMBackup *backup, BMEditMesh *em, bool recalc_looptri) { BMesh *tmpbm; - if (!em || !backup.bmcopy) { - return; - } BM_mesh_data_free(em->bm); - tmpbm = BM_mesh_copy(backup.bmcopy); + tmpbm = BM_mesh_copy(backup->bmcopy); *em->bm = *tmpbm; MEM_freeN(tmpbm); tmpbm = NULL; - if (recalctess) { + if (recalc_looptri) { BKE_editmesh_looptri_calc(em); } } -void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess) +/** + * Delete the backup, flushing it to an edit-mesh. + */ +void EDBM_redo_state_restore_and_free(BMBackup *backup, BMEditMesh *em, bool recalc_looptri) { - if (em && backup->bmcopy) { - BM_mesh_data_free(em->bm); - *em->bm = *backup->bmcopy; - } - else if (backup->bmcopy) { - BM_mesh_data_free(backup->bmcopy); + BM_mesh_data_free(em->bm); + *em->bm = *backup->bmcopy; + MEM_freeN(backup->bmcopy); + backup->bmcopy = NULL; + if (recalc_looptri) { + BKE_editmesh_looptri_calc(em); } +} +void EDBM_redo_state_free(BMBackup *backup) +{ if (backup->bmcopy) { + BM_mesh_data_free(backup->bmcopy); MEM_freeN(backup->bmcopy); } - backup->bmcopy = NULL; - - if (recalctess && em) { - BKE_editmesh_looptri_calc(em); - } } /** \} */ @@ -132,75 +134,76 @@ bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char * return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - va_end(list); return true; } -/* returns 0 on error, 1 on success. executes and finishes a bmesh operator */ +/** + * The return value: + * - False on error (the mesh must not be changed). + * - True on success, executes and finishes a #BMesh operator. + */ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report) { const char *errmsg; - BMO_op_finish(em->bm, bmop); - - if (BMO_error_get(em->bm, &errmsg, NULL)) { - BMEditMesh *emcopy = em->emcopy; +#ifndef NDEBUG + struct { + int verts_len, edges_len, loops_len, faces_len; + } em_state_prev = { + .verts_len = em->bm->totvert, + .edges_len = em->bm->totedge, + .loops_len = em->bm->totloop, + .faces_len = em->bm->totface, + }; +#endif - if (do_report) { - BKE_report(op->reports, RPT_ERROR, errmsg); - } + BMO_op_finish(em->bm, bmop); - EDBM_mesh_free(em); - *em = *emcopy; - - MEM_freeN(emcopy); - em->emcopyusers = 0; - em->emcopy = NULL; - - /** - * Note, we could pass in the mesh, however this is an exceptional case, allow a slow lookup. - * - * This is needed because the COW mesh makes a full copy of the #BMEditMesh - * instead of sharing the pointer, tagging since this has been freed above, - * the #BMEditMesh.emcopy needs to be flushed to the COW edit-mesh, see T55457. - */ - { - Main *bmain = G_MAIN; - for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) { - if (mesh->edit_mesh == em) { - DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE); - break; - } + bool changed = false; + bool changed_was_set = false; + + eBMOpErrorLevel level; + while (BMO_error_pop(em->bm, &errmsg, NULL, &level)) { + ReportType type = RPT_INFO; + switch (level) { + case BMO_ERROR_CANCEL: { + changed_was_set = true; + break; + } + case BMO_ERROR_WARN: { + type = RPT_WARNING; + changed_was_set = true; + changed = true; + break; + } + case BMO_ERROR_FATAL: { + type = RPT_ERROR; + changed_was_set = true; + changed = true; + break; } } - /* when copying, tessellation isn't to for faster copying, - * but means we need to re-tessellate here */ - if (em->looptris == NULL) { - BKE_editmesh_looptri_calc(em); + if (do_report) { + BKE_report(op->reports, type, errmsg); } - - return false; } - - em->emcopyusers--; - if (em->emcopyusers < 0) { - printf("warning: em->emcopyusers was less than zero.\n"); + if (changed_was_set == false) { + changed = true; } - if (em->emcopyusers <= 0) { - BKE_editmesh_free(em->emcopy); - MEM_freeN(em->emcopy); - em->emcopy = NULL; +#ifndef NDEBUG + if (changed == false) { + BLI_assert((em_state_prev.verts_len == em->bm->totvert) && + (em_state_prev.edges_len == em->bm->totedge) && + (em_state_prev.loops_len == em->bm->totloop) && + (em_state_prev.faces_len == em->bm->totface)); } +#endif - return true; + return changed; } bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) @@ -217,11 +220,6 @@ bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); va_end(list); @@ -249,11 +247,6 @@ bool EDBM_op_call_and_selectf(BMEditMesh *em, return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out); @@ -284,11 +277,6 @@ bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...) return false; } - if (!em->emcopy) { - em->emcopy = BKE_editmesh_copy(em); - } - em->emcopyusers++; - BMO_op_exec(bm, &bmop); va_end(list); @@ -317,17 +305,13 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) if (me->edit_mesh) { /* this happens when switching shape keys */ - EDBM_mesh_free(me->edit_mesh); + EDBM_mesh_free_data(me->edit_mesh); MEM_freeN(me->edit_mesh); } - /* currently executing operators re-tessellates, so we can avoid doing here - * but at some point it may need to be added back. */ -#if 0 - me->edit_mesh = BKE_editmesh_create(bm, true); -#else - me->edit_mesh = BKE_editmesh_create(bm, false); -#endif + /* Executing operators re-tessellates, + * so we can avoid doing here but at some point it may need to be added back. */ + me->edit_mesh = BKE_editmesh_create(bm); me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode; me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0; @@ -338,7 +322,8 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) /** * \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates). - * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 + * Most callers should run #DEG_id_tag_update on `ob->data`, see: T46738, T46913. + * This ensures #BKE_object_free_derived_caches runs on all objects that use this mesh. */ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) { @@ -358,25 +343,6 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) .calc_object_remap = true, .update_shapekey_indices = !free_data, })); - - /* Free derived mesh. usually this would happen through depsgraph but there - * are exceptions like file save that will not cause this, and we want to - * avoid ending up with an invalid derived mesh then. - * - * Do it for all objects which shares the same mesh datablock, since their - * derived meshes might also be referencing data which was just freed, - * - * Annoying enough, but currently seems most efficient way to avoid access - * of freed data on scene update, especially in cases when there are dependency - * cycles. - */ -#if 0 - for (Object *other_object = bmain->objects.first; other_object != NULL; other_object = other_object->id.next) { - if (other_object->data == ob->data) { - BKE_object_free_derived_caches(other_object); - } - } -#endif } void EDBM_mesh_clear(BMEditMesh *em) @@ -384,8 +350,8 @@ void EDBM_mesh_clear(BMEditMesh *em) /* clear bmesh */ BM_mesh_clear(em->bm); - /* free derived meshes */ - BKE_editmesh_free_derivedmesh(em); + /* Free evaluated meshes & cache. */ + BKE_editmesh_free_derived_caches(em); /* free tessellation data */ em->tottri = 0; @@ -401,9 +367,9 @@ void EDBM_mesh_load(Main *bmain, Object *ob) } /** - * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free + * Should only be called on the active edit-mesh, otherwise call #BKE_editmesh_free_data. */ -void EDBM_mesh_free(BMEditMesh *em) +void EDBM_mesh_free_data(BMEditMesh *em) { /* These tables aren't used yet, so it's not strictly necessary * to 'end' them but if someone tries to start using them, @@ -411,7 +377,7 @@ void EDBM_mesh_free(BMEditMesh *em) ED_mesh_mirror_spatial_table_end(NULL); ED_mesh_mirror_topo_table_end(NULL); - BKE_editmesh_free(em); + BKE_editmesh_free_data(em); } /** \} */ @@ -1472,7 +1438,7 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params) } if (params->is_destructive) { - /* TODO. we may be able to remove this now! - Campbell */ + /* TODO(campbell): we may be able to remove this now! */ // BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP); } else { @@ -1483,8 +1449,8 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params) BM_lnorspace_invalidate(em->bm, false); em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET; } - /* don't keep stale derivedMesh data around, see: T38872. */ - BKE_editmesh_free_derivedmesh(em); + /* Don't keep stale evaluated mesh data around, see: T38872. */ + BKE_editmesh_free_derived_caches(em); #ifdef DEBUG { diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 7c6dc6516ed..73b3fb9724e 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -34,6 +34,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_report.h" @@ -252,7 +253,7 @@ void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me) WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } -/* note: keep in sync with ED_mesh_color_add */ +/* NOTE: keep in sync with #ED_mesh_color_add. */ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; @@ -377,7 +378,7 @@ bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name) return false; } -/* note: keep in sync with ED_mesh_uv_texture_add */ +/* NOTE: keep in sync with #ED_mesh_uv_texture_add. */ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; @@ -483,7 +484,7 @@ bool ED_mesh_color_remove_named(Mesh *me, const char *name) /*********************** Sculpt Vertex colors operators ************************/ -/* note: keep in sync with ED_mesh_uv_texture_add */ +/* NOTE: keep in sync with #ED_mesh_uv_texture_add. */ int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool active_set, const bool do_init) { BMEditMesh *em; diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c index 25d3eaf11d4..5eb69aab48b 100644 --- a/source/blender/editors/mesh/mesh_mirror.c +++ b/source/blender/editors/mesh/mesh_mirror.c @@ -308,8 +308,9 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em, last = 0; - /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, - * but you can't ever access the last 'a' index of MirrTopoPairs */ + /* Get the pairs out of the sorted hashes. + * NOTE: `totvert + 1` means we can use the previous 2, + * but you can't ever access the last 'a' index of #MirrTopoPairs. */ if (em) { BMVert **vtable = em->bm->vtable; for (a = 1; a <= totvert; a++) { diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index f306612f295..27fb21e1dfb 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -390,7 +390,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) CTX_DATA_END; /* Apply parent transform if the active object's parent was joined to it. - * Note: This doesn't apply recursive parenting. */ + * NOTE: This doesn't apply recursive parenting. */ if (join_parent) { ob->parent = NULL; BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false); @@ -475,16 +475,17 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) me = ob_iter->data; /* Join this object's vertex groups to the base one's */ - for (dg = ob_iter->defbase.first; dg; dg = dg->next) { + for (dg = me->vertex_group_names.first; dg; dg = dg->next) { /* See if this group exists in the object (if it doesn't, add it to the end) */ if (!BKE_object_defgroup_find_name(ob, dg->name)) { odg = MEM_mallocN(sizeof(bDeformGroup), "join deformGroup"); memcpy(odg, dg, sizeof(bDeformGroup)); - BLI_addtail(&ob->defbase, odg); + BLI_addtail(&mesh_active->vertex_group_names, odg); } } - if (ob->defbase.first && ob->actdef == 0) { - ob->actdef = 1; + if (!BLI_listbase_is_empty(&mesh_active->vertex_group_names) && + me->vertex_group_active_index == 0) { + me->vertex_group_active_index = 1; } /* Join this object's face maps to the base one's. */ @@ -1060,7 +1061,7 @@ static float *editmesh_get_mirror_uv( cent_vec[1] = face_cent[1]; } - /* TODO - Optimize */ + /* TODO: Optimize. */ { BMIter iter; BMFace *efa; @@ -1473,19 +1474,21 @@ bool ED_mesh_pick_vert( MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve) { - if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) { + if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH) { Mesh *me = ob->data; - BMesh *bm = me->edit_mesh->bm; - const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); + if (!BLI_listbase_is_empty(&me->vertex_group_names)) { + BMesh *bm = me->edit_mesh->bm; + const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); - if (cd_dvert_offset != -1) { - BMVert *eve = BM_mesh_active_vert_get(bm); + if (cd_dvert_offset != -1) { + BMVert *eve = BM_mesh_active_vert_get(bm); - if (eve) { - if (r_eve) { - *r_eve = eve; + if (eve) { + if (r_eve) { + *r_eve = eve; + } + return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); } - return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); } } } |