diff options
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r-- | source/blender/editors/mesh/editface.c | 3 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_bevel.c | 236 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife.c | 2 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_rip.c | 2 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 6 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 10 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_undo.c | 91 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_utils.c | 25 |
8 files changed, 220 insertions, 155 deletions
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 01be8f848aa..c4e87614732 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -53,6 +53,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "GPU_draw.h" #include "GPU_buffers.h" /* own include */ @@ -433,7 +434,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten if (ENDIAN_ORDER == B_ENDIAN) { IMB_convert_rgba_to_abgr(ibuf); } - WM_framebuffer_to_index_array(ibuf->rect, size[0] * size[1]); + GPU_select_to_index_array(ibuf->rect, size[0] * size[1]); a = size[0] * size[1]; while (a--) { diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 242cbf79a83..302ca407add 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -58,26 +58,45 @@ #define MVAL_PIXEL_MARGIN 5.0f +/* until implement profile = 0 case, need to clamp somewhat above zero */ +#define PROFILE_HARD_MIN 0.15f + +#define SEGMENTS_HARD_MAX 1000 + +/* which value is mouse movement and numeric input controlling? */ +#define OFFSET_VALUE 0 +#define OFFSET_VALUE_PERCENT 1 +#define PROFILE_VALUE 2 +#define SEGMENTS_VALUE 3 +#define NUM_VALUE_KINDS 4 + +static const char *value_rna_name[NUM_VALUE_KINDS] = {"offset", "offset", "profile", "segments"}; +static const float value_clamp_min[NUM_VALUE_KINDS] = {0.0f, 0.0f, PROFILE_HARD_MIN, 1.0f}; +static const float value_clamp_max[NUM_VALUE_KINDS] = {1e6, 100.0f, 1.0f, SEGMENTS_HARD_MAX}; +static const float value_start[NUM_VALUE_KINDS] = {0.0f, 0.0f, 0.5f, 1.0f}; +static const float value_scale_per_inch[NUM_VALUE_KINDS] = { 0.0f, 100.0f, 1.0f, 4.0f}; + typedef struct { BMEditMesh *em; - float initial_length; - float pixel_size; /* use when mouse input is interpreted as spatial distance */ + float initial_length[NUM_VALUE_KINDS]; + float scale[NUM_VALUE_KINDS]; + NumInput num_input[NUM_VALUE_KINDS]; + float shift_value[NUM_VALUE_KINDS]; /* The current value when shift is pressed. Negative when shift not active. */ bool is_modal; - NumInput num_input; - float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */ /* modal only */ float mcenter[2]; BMBackup mesh_backup; void *draw_handle_pixel; short twtype; + short value_mode; /* Which value does mouse movement and numeric input affect? */ float segments; /* Segments as float so smooth mouse pan works in small increments */ } BevelData; static void edbm_bevel_update_header(bContext *C, wmOperator *op) { const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Mode: %s (M), Clamp Overlap: %s (C), " - "Vertex Only: %s (V), Offset: %s, Segments: %d"); + "Vertex Only: %s (V), Profile Control: %s (P), Offset: %s, Segments: %d, Profile: %.3f"); char msg[UI_MAX_DRAW_STR]; ScrArea *sa = CTX_wm_area(C); @@ -89,8 +108,8 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op) const char *type_str; PropertyRNA *prop = RNA_struct_find_property(op->ptr, "offset_type"); - if (hasNumInput(&opdata->num_input)) { - outputNumInput(&opdata->num_input, offset_str, &sce->unit); + if (hasNumInput(&opdata->num_input[OFFSET_VALUE])) { + outputNumInput(&opdata->num_input[OFFSET_VALUE], offset_str, &sce->unit); } else { BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset")); @@ -101,7 +120,8 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op) BLI_snprintf(msg, sizeof(msg), str, type_str, WM_bool_as_string(RNA_boolean_get(op->ptr, "clamp_overlap")), WM_bool_as_string(RNA_boolean_get(op->ptr, "vertex_only")), - offset_str, RNA_int_get(op->ptr, "segments")); + WM_bool_as_string(opdata->value_mode == PROFILE_VALUE), + offset_str, RNA_int_get(op->ptr, "segments"), RNA_float_get(op->ptr, "profile")); ED_area_headerprint(sa, msg); } @@ -113,6 +133,8 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) Scene *scene = CTX_data_scene(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BevelData *opdata; + float pixels_per_inch; + int i; if (em->bm->totvertsel == 0) { return false; @@ -122,13 +144,25 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) opdata->em = em; opdata->is_modal = is_modal; - opdata->shift_factor = -1.0f; - - initNumInput(&opdata->num_input); - opdata->num_input.idx_max = 0; - opdata->num_input.val_flag[0] |= NUM_NO_NEGATIVE; - opdata->num_input.unit_sys = scene->unit.system; - opdata->num_input.unit_type[0] = B_UNIT_NONE; /* Not sure this is a factor or a unit? */ + opdata->value_mode = OFFSET_VALUE; + pixels_per_inch = U.dpi * U.pixelsize; + + for (i = 0; i < NUM_VALUE_KINDS; i++) { + opdata->shift_value[i] = -1.0f; + /* 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]); + opdata->num_input[i].idx_max = 0; + opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE; + if (i == SEGMENTS_VALUE) { + opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO; + } + if (i == OFFSET_VALUE) { + opdata->num_input[i].unit_sys = scene->unit.system; + } + opdata->num_input[i].unit_type[0] = B_UNIT_NONE; /* Not sure this is a factor or a unit? */ + } /* avoid the cost of allocating a bm copy */ if (is_modal) { @@ -136,7 +170,8 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) ARegion *ar = CTX_wm_region(C); opdata->mesh_backup = EDBM_redo_state_store(em); - opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); + opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, + opdata->mcenter, REGION_DRAW_POST_PIXEL); G.moving = G_TRANSFORM_EDIT; if (v3d) { @@ -167,13 +202,15 @@ static bool edbm_bevel_calc(wmOperator *op) EDBM_redo_state_restore(opdata->mesh_backup, em, false); } - if (em->ob) + if (em->ob) { material = CLAMPIS(material, -1, em->ob->totcol - 1); + } EDBM_op_init(em, &bmop, op, "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b " "material=%i loop_slide=%b", - BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, clamp_overlap, material, loop_slide); + BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, + clamp_overlap, material, loop_slide); BMO_op_exec(em->bm, &bmop); @@ -185,8 +222,9 @@ static bool edbm_bevel_calc(wmOperator *op) } /* no need to de-select existing geometry */ - if (!EDBM_op_finish(em, &bmop, op, true)) + if (!EDBM_op_finish(em, &bmop, op, true)) { return false; + } EDBM_mesh_normals_update(opdata->em); @@ -250,12 +288,37 @@ static int edbm_bevel_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed) +{ + BevelData *opdata; + float mlen[2], len, value, sc, st; + int vmode; + + opdata = op->customdata; + mlen[0] = opdata->mcenter[0] - event->mval[0]; + mlen[1] = opdata->mcenter[1] - event->mval[1]; + len = len_v2(mlen); + vmode = opdata->value_mode; + if (mode_changed) { + /* If current value is not default start value, adjust len so that + * the scaling and offset in edbm_bevel_mouse_set_value will + * start at current value */ + value = (vmode == SEGMENTS_VALUE) ? + opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]); + sc = opdata->scale[vmode]; + st = value_start[vmode]; + if (value != value_start[vmode]) { + len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc; + } + } + opdata->initial_length[opdata->value_mode] = len; +} + static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* TODO make modal keymap (see fly mode) */ RegionView3D *rv3d = CTX_wm_region_view3d(C); BevelData *opdata; - float mlen[2]; float center_3d[3]; if (!edbm_bevel_init(C, op, true)) { @@ -270,10 +333,10 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event) * ideally this will never happen and should be checked for above */ opdata->mcenter[0] = opdata->mcenter[1] = 0; } - mlen[0] = opdata->mcenter[0] - event->mval[0]; - mlen[1] = opdata->mcenter[1] - event->mval[1]; - opdata->initial_length = len_v2(mlen); - opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f; + edbm_bevel_calc_initial_length(op, event, false); + + /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */ + opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f; edbm_bevel_update_header(C, op); @@ -287,59 +350,72 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event) +static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event) { BevelData *opdata = op->customdata; - bool use_dist; - bool is_percent; + int vmode = opdata->value_mode; float mdiff[2]; - float factor; + float value; mdiff[0] = opdata->mcenter[0] - event->mval[0]; mdiff[1] = opdata->mcenter[1] - event->mval[1]; - is_percent = (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT); - use_dist = !is_percent; - factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size; + value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]); + + /* Scale according to value mode */ + value = value_start[vmode] + value * opdata->scale[vmode]; /* Fake shift-transform... */ if (event->shift) { - if (opdata->shift_factor < 0.0f) { - opdata->shift_factor = RNA_float_get(op->ptr, "offset"); - if (is_percent) { - opdata->shift_factor /= 100.0f; - } + if (opdata->shift_value[vmode] < 0.0f) { + opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ? + opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]); } - factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor; + value = (value - opdata->shift_value[vmode]) * 0.1f + opdata->shift_value[vmode]; } - else if (opdata->shift_factor >= 0.0f) { - opdata->shift_factor = -1.0f; + else if (opdata->shift_value[vmode] >= 0.0f) { + opdata->shift_value[vmode] = -1.0f; } - /* clamp differently based on distance/factor */ - if (use_dist) { - if (factor < 0.0f) factor = 0.0f; + /* clamp accordingto value mode, and store value back */ + CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]); + if (vmode == SEGMENTS_VALUE) { + opdata->segments = value; + RNA_int_set(op->ptr, "segments", (int)(value + 0.5f)); } else { - CLAMP(factor, 0.0f, 1.0f); - if (is_percent) { - factor *= 100.0f; - } + RNA_float_set(op->ptr, value_rna_name[vmode], value); } +} - return factor; +static void edbm_bevel_numinput_set_value(wmOperator *op) +{ + BevelData *opdata = op->customdata; + float value; + int vmode; + + vmode = opdata->value_mode; + value = (vmode == SEGMENTS_VALUE) ? + opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]); + applyNumInput(&opdata->num_input[vmode], &value); + CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]); + if (vmode == SEGMENTS_VALUE) { + opdata->segments = value; + RNA_int_set(op->ptr, "segments", (int)value); + } + else { + RNA_float_set(op->ptr, value_rna_name[vmode], value); + } } static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) { BevelData *opdata = op->customdata; - const bool has_numinput = hasNumInput(&opdata->num_input); + const bool has_numinput = hasNumInput(&opdata->num_input[opdata->value_mode]); /* Modal numinput active, try to handle numeric inputs first... */ - if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input, event)) { - float value = RNA_float_get(op->ptr, "offset"); - applyNumInput(&opdata->num_input, &value); - RNA_float_set(op->ptr, "offset", value); + if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) { + edbm_bevel_numinput_set_value(op); edbm_bevel_calc(op); edbm_bevel_update_header(C, op); return OPERATOR_RUNNING_MODAL; @@ -354,9 +430,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) case MOUSEMOVE: if (!has_numinput) { - const float factor = edbm_bevel_mval_factor(op, event); - RNA_float_set(op->ptr, "offset", factor); - + edbm_bevel_mouse_set_value(op, event); edbm_bevel_calc(op); edbm_bevel_update_header(C, op); handled = true; @@ -426,12 +500,18 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) if (type > BEVEL_AMT_PERCENT) { type = BEVEL_AMT_OFFSET; } + if (opdata->value_mode == OFFSET_VALUE && type == BEVEL_AMT_PERCENT) + opdata->value_mode = OFFSET_VALUE_PERCENT; + else if (opdata->value_mode == OFFSET_VALUE_PERCENT && type != BEVEL_AMT_PERCENT) + opdata->value_mode = OFFSET_VALUE; RNA_property_enum_set(op->ptr, prop, type); } - /* Update factor accordingly to new offset_type. */ - if (!has_numinput) { - RNA_float_set(op->ptr, "offset", edbm_bevel_mval_factor(op, event)); - } + /* Update offset accordingly to new offset_type. */ + if (!has_numinput && + (opdata->value_mode == OFFSET_VALUE || opdata->value_mode == OFFSET_VALUE_PERCENT)) + { + edbm_bevel_mouse_set_value(op, event); + } edbm_bevel_calc(op); edbm_bevel_update_header(C, op); handled = true; @@ -448,6 +528,28 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) edbm_bevel_update_header(C, op); handled = true; break; + case PKEY: + if (event->val == KM_RELEASE) + break; + if (opdata->value_mode == PROFILE_VALUE) { + opdata->value_mode = OFFSET_VALUE; + } + else { + opdata->value_mode = PROFILE_VALUE; + } + edbm_bevel_calc_initial_length(op, event, true); + break; + case SKEY: + if (event->val == KM_RELEASE) + break; + if (opdata->value_mode == SEGMENTS_VALUE) { + opdata->value_mode = OFFSET_VALUE; + } + else { + opdata->value_mode = SEGMENTS_VALUE; + } + edbm_bevel_calc_initial_length(op, event, true); + break; case VKEY: if (event->val == KM_RELEASE) break; @@ -464,10 +566,8 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* Modal numinput inactive, try to handle numeric inputs last... */ - if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input, event)) { - float value = RNA_float_get(op->ptr, "offset"); - applyNumInput(&opdata->num_input, &value); - RNA_float_set(op->ptr, "offset", value); + if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) { + edbm_bevel_numinput_set_value(op); edbm_bevel_calc(op); edbm_bevel_update_header(C, op); return OPERATOR_RUNNING_MODAL; @@ -518,11 +618,13 @@ void MESH_OT_bevel(wmOperatorType *ot) RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures"); prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f); RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func); - RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8); - RNA_def_float(ot->srna, "profile", 0.5f, 0.15f, 1.0f, "Profile", "Controls profile shape (0.5 = round)", 0.15f, 1.0f); + RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8); + RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile", + "Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f); RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex Only", "Bevel only vertices"); RNA_def_boolean(ot->srna, "clamp_overlap", false, "Clamp Overlap", - "Do not allow beveled edges/vertices to overlap each other"); + "Do not allow beveled edges/vertices to overlap each other"); RNA_def_boolean(ot->srna, "loop_slide", true, "Loop Slide", "Prefer slide along edge to even widths"); - RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material", "Material for bevel faces (-1 means use adjacent faces)", -1, 100); + RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material", + "Material for bevel faces (-1 means use adjacent faces)", -1, 100); } diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 0fd56fbcc4e..a84b8d9dcc8 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2283,7 +2283,7 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe BMEdge **edge_array = BLI_array_alloca(edge_array, edge_array_len); - /* point to knife edges we've created edges in, edge_array aligned */ + /* point to knife edges we've created edges in, edge_array aligned */ KnifeEdge **kfe_array = BLI_array_alloca(kfe_array, edge_array_len); BLI_assert(BLI_gset_size(kcd->edgenet.edge_visit) == 0); diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 9e71e646b1a..8868827a11f 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -463,7 +463,7 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u if ((ulp->l_pair[0] && ulp->l_pair[1]) && (ulp->l_pair[0]->e != ulp->l_pair[1]->e)) { - /* time has come to make a face! */ + /* time has come to make a face! */ BMVert *v_shared = BM_edge_share_vert(ulp->l_pair[0]->e, ulp->l_pair[1]->e); BMFace *f, *f_example = ulp->l_pair[0]->f; BMLoop *l_iter; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 84ae35fae6e..5d5731a7e16 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2453,7 +2453,7 @@ static void select_linked_delimit_begin(BMesh *bm, int delimit) const bool is_walk_ok = ( (select_linked_delimit_test(e, delimit, &delimit_data) == false)); - BMO_elem_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); + BMO_edge_flag_set(bm, e, BMO_ELE_TAG, is_walk_ok); } } } @@ -2496,7 +2496,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) if (delimit) { BMEdge *e; BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - if (!BMO_elem_flag_test(bm, e, BMO_ELE_TAG)) { + if (!BMO_edge_flag_test(bm, e, BMO_ELE_TAG)) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); BM_elem_flag_disable(e->v2, BM_ELEM_TAG); } @@ -2552,7 +2552,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { BM_elem_flag_set( e, BM_ELEM_TAG, - (BM_elem_flag_test(e, BM_ELEM_SELECT) && BMO_elem_flag_test(bm, e, BMO_ELE_TAG))); + (BM_elem_flag_test(e, BM_ELEM_SELECT) && BMO_edge_flag_test(bm, e, BMO_ELE_TAG))); } } else { diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index efe179790da..9f1602ccfaf 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -2910,7 +2910,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) } } - BMO_elem_flag_set(bm, be, ELE_EDGE_CUT, is_cut); + BMO_edge_flag_set(bm, be, ELE_EDGE_CUT, is_cut); } @@ -2982,7 +2982,9 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe Object *obedit = base_old->object; BMesh *bm_new; - bm_new = BM_mesh_create(&bm_mesh_allocsize_default); + bm_new = BM_mesh_create( + &bm_mesh_allocsize_default, + &((struct BMeshCreateParams){.use_toolflags = true,})); BM_mesh_elem_toolflags_ensure(bm_new); /* needed for 'duplicate' bmo */ CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0); @@ -3294,7 +3296,9 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) BMesh *bm_old = NULL; int retval_iter = 0; - bm_old = BM_mesh_create(&bm_mesh_allocsize_default); + bm_old = BM_mesh_create( + &bm_mesh_allocsize_default, + &((struct BMeshCreateParams){.use_toolflags = true,})); BM_mesh_bm_from_me(bm_old, me, (&(struct BMeshFromMeshParams){0})); diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index b9d3fd6c8be..b44fbc3ce45 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -49,7 +49,7 @@ # endif # include "BLI_array_store.h" -# include "BLI_math_base.h" +# include "BLI_array_store_utils.h" /* check on best size later... */ # define ARRAY_CHUNK_SIZE 256 @@ -89,8 +89,7 @@ typedef struct UndoMesh { #ifdef USE_ARRAY_STORE /* NULL arrays are considered empty */ - struct { - /* most data is stored as 'custom' data */ + struct { /* most data is stored as 'custom' data */ BArrayCustomData *vdata, *edata, *ldata, *pdata; BArrayState **keyblocks; BArrayState *mselect; @@ -105,8 +104,7 @@ typedef struct UndoMesh { * \{ */ static struct { - BArrayStore **bs_all; - int bs_all_len; + struct BArrayStore_AtSize bs_stride; int users; /* We could have the undo API pass in the previous state, for now store a local list */ @@ -118,57 +116,6 @@ static struct { } um_arraystore = {NULL}; -static BArrayStore *array_store_at_size_ensure(const int stride) -{ - if (um_arraystore.bs_all_len < stride) { - um_arraystore.bs_all_len = stride; - um_arraystore.bs_all = MEM_recallocN(um_arraystore.bs_all, sizeof(*um_arraystore.bs_all) * stride); - } - BArrayStore **bs_p = &um_arraystore.bs_all[stride - 1]; - - if ((*bs_p) == NULL) { -#if 0 - unsigned int chunk_count = ARRAY_CHUNK_SIZE; -#else - /* calculate best chunk-count to fit a power of two */ - unsigned int chunk_count = ARRAY_CHUNK_SIZE; - { - unsigned int size = chunk_count * stride; - size = power_of_2_max_u(size); - size = MEM_SIZE_OPTIMAL(size); - chunk_count = size / stride; - } -#endif - - (*bs_p) = BLI_array_store_create(stride, chunk_count); - } - return *bs_p; -} - -static BArrayStore *array_store_at_size_get(const int stride) -{ - BLI_assert(stride > 0 && stride <= um_arraystore.bs_all_len); - return um_arraystore.bs_all[stride - 1]; -} - -#ifdef DEBUG_PRINT -static void um_arraystore_memory_usage(size_t *r_size_expanded, size_t *r_size_compacted) -{ - size_t size_compacted = 0; - size_t size_expanded = 0; - for (int i = 0; i < um_arraystore.bs_all_len; i++) { - BArrayStore *bs = um_arraystore.bs_all[i]; - if (bs) { - size_compacted += BLI_array_store_calc_size_compacted_get(bs); - size_expanded += BLI_array_store_calc_size_expanded_get(bs); - } - } - - *r_size_expanded = size_expanded; - *r_size_compacted = size_compacted; -} -#endif - static void um_arraystore_cd_compact( struct CustomData *cdata, const size_t data_len, bool create, @@ -194,7 +141,7 @@ static void um_arraystore_cd_compact( } const int stride = CustomData_sizeof(type); - BArrayStore *bs = create ? array_store_at_size_ensure(stride) : NULL; + BArrayStore *bs = create ? BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE) : NULL; const int layer_len = layer_end - layer_start; if (create) { @@ -299,7 +246,7 @@ static void um_arraystore_cd_free(BArrayCustomData *bcd) while (bcd) { BArrayCustomData *bcd_next = bcd->next; const int stride = CustomData_sizeof(bcd->type); - BArrayStore *bs = array_store_at_size_get(stride); + BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride); for (int i = 0; i < bcd->states_len; i++) { if (bcd->states[i]) { BLI_array_store_state_remove(bs, bcd->states[i]); @@ -328,7 +275,7 @@ static void um_arraystore_compact_ex( if (me->key && me->key->totkey) { const size_t stride = me->key->elemsize; - BArrayStore *bs = create ? array_store_at_size_ensure(stride) : NULL; + BArrayStore *bs = create ? BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE) : NULL; if (create) { um->store.keyblocks = MEM_mallocN(me->key->totkey * sizeof(*um->store.keyblocks), __func__); } @@ -355,7 +302,7 @@ static void um_arraystore_compact_ex( if (create) { BArrayState *state_reference = um_ref ? um_ref->store.mselect : NULL; const size_t stride = sizeof(*me->mselect); - BArrayStore *bs = array_store_at_size_ensure(stride); + BArrayStore *bs = BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE); um->store.mselect = BLI_array_store_state_add( bs, me->mselect, (size_t)me->totselect * stride, state_reference); } @@ -384,7 +331,7 @@ static void um_arraystore_compact_with_info(UndoMesh *um, const UndoMesh *um_ref { #ifdef DEBUG_PRINT size_t size_expanded_prev, size_compacted_prev; - um_arraystore_memory_usage(&size_expanded_prev, &size_compacted_prev); + BLI_array_store_at_size_calc_memory_usage(&um_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev); #endif #ifdef DEBUG_TIME @@ -400,7 +347,7 @@ static void um_arraystore_compact_with_info(UndoMesh *um, const UndoMesh *um_ref #ifdef DEBUG_PRINT { size_t size_expanded, size_compacted; - um_arraystore_memory_usage(&size_expanded, &size_compacted); + BLI_array_store_at_size_calc_memory_usage(&um_arraystore.bs_stride, &size_expanded, &size_compacted); const double percent_total = size_expanded ? (((double)size_compacted / (double)size_expanded) * 100.0) : -1.0; @@ -483,7 +430,7 @@ static void um_arraystore_free(UndoMesh *um) if (um->store.keyblocks) { const size_t stride = me->key->elemsize; - BArrayStore *bs = array_store_at_size_get(stride); + BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride); for (int i = 0; i < me->key->totkey; i++) { BArrayState *state = um->store.keyblocks[i]; BLI_array_store_state_remove(bs, state); @@ -494,7 +441,7 @@ static void um_arraystore_free(UndoMesh *um) if (um->store.mselect) { const size_t stride = sizeof(*me->mselect); - BArrayStore *bs = array_store_at_size_get(stride); + BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride); BArrayState *state = um->store.mselect; BLI_array_store_state_remove(bs, state); um->store.mselect = NULL; @@ -508,15 +455,7 @@ static void um_arraystore_free(UndoMesh *um) #ifdef DEBUG_PRINT printf("mesh undo store: freeing all data!\n"); #endif - for (int i = 0; i < um_arraystore.bs_all_len; i += 1) { - if (um_arraystore.bs_all[i]) { - BLI_array_store_destroy(um_arraystore.bs_all[i]); - } - } - - MEM_freeN(um_arraystore.bs_all); - um_arraystore.bs_all = NULL; - um_arraystore.bs_all_len = 0; + BLI_array_store_at_size_clear(&um_arraystore.bs_stride); #ifdef USE_ARRAY_STORE_THREAD BLI_task_pool_free(um_arraystore.task_pool); @@ -624,7 +563,9 @@ static void undoMesh_to_editbtMesh(void *um_v, void *em_v, void *obdata) EDBM_mesh_free(em); - bm = BM_mesh_create(&allocsize); + bm = BM_mesh_create( + &allocsize, + &((struct BMeshCreateParams){.use_toolflags = true,})); BM_mesh_bm_from_me( bm, &um->me, (&(struct BMeshFromMeshParams){ @@ -698,7 +639,7 @@ static void free_undo(void *um_v) MEM_freeN(me->key); } - BKE_mesh_free(me, false); + BKE_mesh_free(me); MEM_freeN(me); } diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 99be37845ee..5101608246a 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -354,7 +354,9 @@ void EDBM_mesh_make(ToolSettings *ts, Object *ob, const bool add_key_index) BKE_mesh_convert_mfaces_to_mpolys(me); } - bm = BKE_mesh_to_bmesh(me, ob, add_key_index); + bm = BKE_mesh_to_bmesh( + me, ob, add_key_index, + &((struct BMeshCreateParams){.use_toolflags = true,})); if (me->edit_btmesh) { /* this happens when switching shape keys */ @@ -399,10 +401,25 @@ void EDBM_mesh_load(Object *ob) BKE_mesh_tessface_calc(me); #endif - /* free derived mesh. usually this would happen through depsgraph but there + /* 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 */ - BKE_object_free_derived_caches(ob); + * 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. + */ + for (Object *other_object = G.main->object.first; + other_object != NULL; + other_object = other_object->id.next) + { + if (other_object->data == ob->data) { + BKE_object_free_derived_caches(other_object); + } + } } /** |