diff options
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r-- | source/blender/editors/mesh/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/editors/mesh/editface.c | 10 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_bisect.c | 348 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_extrude.c | 407 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife.c | 175 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife_project.c | 13 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_loopcut.c | 56 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_path.c | 16 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_polybuild.c | 541 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_select.c | 116 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 48 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_utils.c | 24 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_data.c | 79 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_intern.h | 5 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_navmesh.c | 25 | ||||
-rw-r--r-- | source/blender/editors/mesh/mesh_ops.c | 25 | ||||
-rw-r--r-- | source/blender/editors/mesh/meshtools.c | 46 |
17 files changed, 1668 insertions, 268 deletions
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 8783367ef7e..80e1187609c 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../blentranslation + ../../depsgraph ../../bmesh ../../gpu ../../imbuf @@ -51,6 +52,7 @@ set(SRC editmesh_knife_project.c editmesh_loopcut.c editmesh_path.c + editmesh_polybuild.c editmesh_rip.c editmesh_rip_edge.c editmesh_select.c diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 6c6c106b19a..870eb68600a 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -106,6 +106,8 @@ void paintface_flush_flags(Object *ob, short flag) /* draw-object caches hidden faces, force re-generation T46867 */ GPU_drawobject_free(dm); } + + BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_ALL); } void paintface_hide(Object *ob, const bool unselected) @@ -387,14 +389,14 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b } /* image window redraw */ - + paintface_flush_flags(ob, SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views return true; } -int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) +int do_paintface_box_select(const struct EvaluationContext *eval_ctx, ViewContext *vc, rcti *rect, bool select, bool extend) { Object *ob = vc->obact; Mesh *me; @@ -425,7 +427,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten } } - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect); rt = ibuf->rect; @@ -515,6 +517,8 @@ void paintvert_flush_flags(Object *ob) dm_mv->flag = me->mvert[i].flag; } } + + BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_ALL); } /* note: if the caller passes false to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */ void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 3a9e278f039..1937a9f6891 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -50,9 +50,17 @@ #include "ED_screen.h" #include "ED_view3d.h" +#include "UI_resources.h" #include "mesh_intern.h" /* own include */ +#define USE_MANIPULATOR + +#ifdef USE_MANIPULATOR +#include "ED_manipulator_library.h" +#include "ED_util.h" +#endif + static int mesh_bisect_exec(bContext *C, wmOperator *op); /* -------------------------------------------------------------------- */ @@ -186,6 +194,16 @@ static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event) if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { edbm_bisect_exit(C, &opdata_back); + +#ifdef USE_MANIPULATOR + /* Setup manipulators */ + { + View3D *v3d = CTX_wm_view3d(C); + if (v3d && (v3d->twtype & V3D_MANIPULATOR_DRAW)) { + WM_manipulator_group_type_ensure("MESH_WGT_bisect"); + } + } +#endif } return ret; @@ -315,6 +333,9 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) } } +#ifdef USE_MANIPULATOR +static void MESH_WGT_bisect(struct wmManipulatorGroupType *wgt); +#endif void MESH_OT_bisect(struct wmOperatorType *ot) { @@ -350,4 +371,331 @@ void MESH_OT_bisect(struct wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1); WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT); + +#ifdef USE_MANIPULATOR + WM_manipulatorgrouptype_append(MESH_WGT_bisect); +#endif +} + + +#ifdef USE_MANIPULATOR + +/* -------------------------------------------------------------------- */ + +/** \name Bisect Manipulator + * \{ */ + +typedef struct ManipulatorGroup { + /* Arrow to change plane depth. */ + struct wmManipulator *translate_z; + /* Translate XYZ */ + struct wmManipulator *translate_c; + /* For grabbing the manipulator and moving freely. */ + struct wmManipulator *rotate_c; + + /* We could store more vars here! */ + struct { + bContext *context; + wmOperator *op; + PropertyRNA *prop_plane_co; + PropertyRNA *prop_plane_no; + + float rotate_axis[3]; + float rotate_up[3]; + } data; +} ManipulatorGroup; + +/** + * XXX. calling redo from property updates is not great. + * This is needed because changing the RNA doesn't cause a redo + * and we're not using operator UI which does just this. + */ +static void manipulator_bisect_exec(ManipulatorGroup *man) +{ + wmOperator *op = man->data.op; + if (op == WM_operator_last_redo((bContext *)man->data.context)) { + ED_undo_operator_repeat((bContext *)man->data.context, op); + } +} + +static void manipulator_mesh_bisect_update_from_op(ManipulatorGroup *man) +{ + wmOperator *op = man->data.op; + + float plane_co[3], plane_no[3]; + + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); + + WM_manipulator_set_matrix_location(man->translate_z, plane_co); + WM_manipulator_set_matrix_location(man->rotate_c, plane_co); + /* translate_c location comes from the property. */ + + WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_z, plane_no); + + WM_manipulator_set_scale(man->translate_c, 0.2); + + RegionView3D *rv3d = ED_view3d_context_rv3d(man->data.context); + if (rv3d) { + normalize_v3_v3(man->data.rotate_axis, rv3d->viewinv[2]); + normalize_v3_v3(man->data.rotate_up, rv3d->viewinv[1]); + + /* ensure its orthogonal */ + project_plane_normalized_v3_v3v3(man->data.rotate_up, man->data.rotate_up, man->data.rotate_axis); + normalize_v3(man->data.rotate_up); + + WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_c, plane_no); + + float plane_no_cross[3]; + cross_v3_v3v3(plane_no_cross, plane_no, man->data.rotate_axis); + + WM_manipulator_set_matrix_offset_rotation_from_yz_axis(man->rotate_c, plane_no_cross, man->data.rotate_axis); + RNA_enum_set(man->rotate_c->ptr, "draw_options", + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR | + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y); + } +} + +/* depth callbacks */ +static void manipulator_bisect_prop_depth_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_co[3], plane_no[3]; + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); + + value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, mpr->matrix_basis[3]); +} + +static void manipulator_bisect_prop_depth_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_co[3], plane[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane); + normalize_v3(plane); + + plane[3] = -value[0] - dot_v3v3(plane, mpr->matrix_basis[3]); + + /* Keep our location, may be offset simply to be inside the viewport. */ + closest_to_plane_normalized_v3(plane_co, plane, plane_co); + + RNA_property_float_set_array(op->ptr, man->data.prop_plane_co, plane_co); + + manipulator_bisect_exec(man); +} + +/* translate callbacks */ +static void manipulator_bisect_prop_translate_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + + BLI_assert(mpr_prop->type->array_length == 3); + UNUSED_VARS_NDEBUG(mpr_prop); + + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, value_p); +} + +static void manipulator_bisect_prop_translate_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + + BLI_assert(mpr_prop->type->array_length == 3); + UNUSED_VARS_NDEBUG(mpr_prop); + + RNA_property_float_set_array(op->ptr, man->data.prop_plane_co, value_p); + + manipulator_bisect_exec(man); +} + +/* angle callbacks */ +static void manipulator_bisect_prop_angle_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_no[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); + normalize_v3(plane_no); + + float plane_no_proj[3]; + project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis); + + if (!is_zero_v3(plane_no_proj)) { + const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis); + value[0] = angle; + } + else { + value[0] = 0.0f; + } +} + +static void manipulator_bisect_prop_angle_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_no[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); + normalize_v3(plane_no); + + float plane_no_proj[3]; + project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis); + + if (!is_zero_v3(plane_no_proj)) { + const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis); + const float angle_delta = angle - angle_compat_rad(value[0], angle); + if (angle_delta != 0.0f) { + float mat[3][3]; + axis_angle_normalized_to_mat3(mat, man->data.rotate_axis, angle_delta); + mul_m3_v3(mat, plane_no); + + /* re-normalize - seems acceptable */ + RNA_property_float_set_array(op->ptr, man->data.prop_plane_no, plane_no); + + manipulator_bisect_exec(man); + } + } +} + +static bool manipulator_mesh_bisect_poll(const bContext *C, wmManipulatorGroupType *wgt) +{ + wmOperator *op = WM_operator_last_redo(C); + if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) { + WM_manipulator_group_type_unlink_delayed_ptr(wgt); + return false; + } + return true; } + +static void manipulator_mesh_bisect_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmOperator *op = WM_operator_last_redo(C); + + if (op == NULL || !STREQ(op->type->idname, "MESH_OT_bisect")) { + return; + } + + struct ManipulatorGroup *man = MEM_callocN(sizeof(ManipulatorGroup), __func__); + mgroup->customdata = man; + + const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true); + const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true); + const wmManipulatorType *wt_dial = WM_manipulatortype_find("MANIPULATOR_WT_dial_3d", true); + + man->translate_z = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + man->translate_c = WM_manipulator_new_ptr(wt_grab, mgroup, NULL); + man->rotate_c = WM_manipulator_new_ptr(wt_dial, mgroup, NULL); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_z->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_c->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, man->rotate_c->color); + + RNA_enum_set(man->translate_z->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_NORMAL); + RNA_enum_set(man->translate_c->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D); + + WM_manipulator_set_flag(man->translate_c, WM_MANIPULATOR_DRAW_VALUE, true); + WM_manipulator_set_flag(man->rotate_c, WM_MANIPULATOR_DRAW_VALUE, true); + + { + man->data.context = (bContext *)C; + man->data.op = op; + man->data.prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co"); + man->data.prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no"); + } + + manipulator_mesh_bisect_update_from_op(man); + + /* Setup property callbacks */ + { + WM_manipulator_target_property_def_func( + man->translate_z, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bisect_prop_depth_get, + .value_set_fn = manipulator_bisect_prop_depth_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->translate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bisect_prop_translate_get, + .value_set_fn = manipulator_bisect_prop_translate_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->rotate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bisect_prop_angle_get, + .value_set_fn = manipulator_bisect_prop_angle_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + } +} + +static void manipulator_mesh_bisect_draw_prepare( + const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + ManipulatorGroup *man = mgroup->customdata; + if (man->data.op->next) { + man->data.op = WM_operator_last_redo((bContext *)man->data.context); + } + manipulator_mesh_bisect_update_from_op(man); +} + +static void MESH_WGT_bisect(struct wmManipulatorGroupType *wgt) +{ + wgt->name = "Mesh Bisect"; + wgt->idname = "MESH_WGT_bisect"; + + wgt->flag = WM_MANIPULATORGROUPTYPE_3D; + + wgt->mmap_params.spaceid = SPACE_VIEW3D; + wgt->mmap_params.regionid = RGN_TYPE_WINDOW; + + wgt->poll = manipulator_mesh_bisect_poll; + wgt->setup = manipulator_mesh_bisect_setup; + wgt->draw_prepare = manipulator_mesh_bisect_draw_prepare; +} + +/** \} */ + +#endif /* USE_MANIPULATOR */ diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 5ac90ec29e6..18320ec65f5 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -45,6 +45,7 @@ #include "RNA_define.h" #include "RNA_access.h" +#include "WM_api.h" #include "WM_types.h" #include "ED_mesh.h" @@ -52,8 +53,19 @@ #include "ED_transform.h" #include "ED_view3d.h" +#include "UI_resources.h" + +#include "MEM_guardedalloc.h" + #include "mesh_intern.h" /* own include */ +#define USE_MANIPULATOR + +#ifdef USE_MANIPULATOR +#include "ED_manipulator_library.h" +#include "ED_util.h" +#endif + static void edbm_extrude_edge_exclude_mirror( Object *obedit, BMEditMesh *em, const char hflag, @@ -747,9 +759,25 @@ static int edbm_spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e } } - return edbm_spin_exec(C, op); + int ret = edbm_spin_exec(C, op); + +#ifdef USE_MANIPULATOR + if (ret & OPERATOR_FINISHED) { + /* Setup manipulators */ + if (v3d && (v3d->twtype & V3D_MANIPULATOR_DRAW)) { + WM_manipulator_group_type_ensure("MESH_WGT_spin"); + } + } +#endif + + return ret; + } +#ifdef USE_MANIPULATOR +static void MESH_WGT_spin(struct wmManipulatorGroupType *wgt); +#endif + void MESH_OT_spin(wmOperatorType *ot) { PropertyRNA *prop; @@ -778,8 +806,385 @@ void MESH_OT_spin(wmOperatorType *ot) "Center", "Center in global view space", -1e4f, 1e4f); RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f); +#ifdef USE_MANIPULATOR + WM_manipulatorgrouptype_append(MESH_WGT_spin); +#endif +} + + +#ifdef USE_MANIPULATOR + +/* -------------------------------------------------------------------- */ + +/** \name Spin Manipulator + * \{ */ + +typedef struct ManipulatorSpinGroup { + /* Arrow to change plane depth. */ + struct wmManipulator *translate_z; + /* Translate XYZ */ + struct wmManipulator *translate_c; + /* For grabbing the manipulator and moving freely. */ + struct wmManipulator *rotate_c; + /* Spin angle */ + struct wmManipulator *angle_z; + + /* We could store more vars here! */ + struct { + bContext *context; + wmOperator *op; + PropertyRNA *prop_axis_co; + PropertyRNA *prop_axis_no; + PropertyRNA *prop_angle; + + float rotate_axis[3]; + float rotate_up[3]; + } data; +} ManipulatorSpinGroup; + +/** + * XXX. calling redo from property updates is not great. + * This is needed because changing the RNA doesn't cause a redo + * and we're not using operator UI which does just this. + */ +static void manipulator_spin_exec(ManipulatorSpinGroup *man) +{ + wmOperator *op = man->data.op; + if (op == WM_operator_last_redo((bContext *)man->data.context)) { + ED_undo_operator_repeat((bContext *)man->data.context, op); + } +} + +static void manipulator_mesh_spin_update_from_op(ManipulatorSpinGroup *man) +{ + wmOperator *op = man->data.op; + + float plane_co[3], plane_no[3]; + + RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no); + + WM_manipulator_set_matrix_location(man->translate_z, plane_co); + WM_manipulator_set_matrix_location(man->rotate_c, plane_co); + WM_manipulator_set_matrix_location(man->angle_z, plane_co); + /* translate_c location comes from the property. */ + + WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_z, plane_no); + WM_manipulator_set_matrix_rotation_from_z_axis(man->angle_z, plane_no); + + WM_manipulator_set_scale(man->translate_c, 0.2); + + RegionView3D *rv3d = ED_view3d_context_rv3d(man->data.context); + if (rv3d) { + normalize_v3_v3(man->data.rotate_axis, rv3d->viewinv[2]); + normalize_v3_v3(man->data.rotate_up, rv3d->viewinv[1]); + + /* ensure its orthogonal */ + project_plane_normalized_v3_v3v3(man->data.rotate_up, man->data.rotate_up, man->data.rotate_axis); + normalize_v3(man->data.rotate_up); + + WM_manipulator_set_matrix_rotation_from_z_axis(man->translate_c, plane_no); + WM_manipulator_set_matrix_rotation_from_yz_axis(man->rotate_c, plane_no, man->data.rotate_axis); + + /* show the axis instead of mouse cursor */ + RNA_enum_set(man->rotate_c->ptr, "draw_options", + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_MIRROR | + ED_MANIPULATOR_DIAL_DRAW_FLAG_ANGLE_START_Y); + + } } +/* depth callbacks */ +static void manipulator_spin_prop_depth_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_co[3], plane_no[3]; + RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no); + + value[0] = dot_v3v3(plane_no, plane_co) - dot_v3v3(plane_no, mpr->matrix_basis[3]); +} + +static void manipulator_spin_prop_depth_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_co[3], plane[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, plane_co); + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane); + normalize_v3(plane); + + plane[3] = -value[0] - dot_v3v3(plane, mpr->matrix_basis[3]); + + /* Keep our location, may be offset simply to be inside the viewport. */ + closest_to_plane_normalized_v3(plane_co, plane, plane_co); + + RNA_property_float_set_array(op->ptr, man->data.prop_axis_co, plane_co); + + manipulator_spin_exec(man); +} + +/* translate callbacks */ +static void manipulator_spin_prop_translate_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 3); + UNUSED_VARS_NDEBUG(mpr_prop); + + RNA_property_float_get_array(op->ptr, man->data.prop_axis_co, value); +} + +static void manipulator_spin_prop_translate_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + + BLI_assert(mpr_prop->type->array_length == 3); + UNUSED_VARS_NDEBUG(mpr_prop); + + RNA_property_float_set_array(op->ptr, man->data.prop_axis_co, value); + + manipulator_spin_exec(man); +} + +/* angle callbacks */ +static void manipulator_spin_prop_axis_angle_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_no[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no); + normalize_v3(plane_no); + + float plane_no_proj[3]; + project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis); + + if (!is_zero_v3(plane_no_proj)) { + const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis); + value[0] = angle; + } + else { + value[0] = 0.0f; + } +} + +static void manipulator_spin_prop_axis_angle_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + const float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + + float plane_no[4]; + RNA_property_float_get_array(op->ptr, man->data.prop_axis_no, plane_no); + normalize_v3(plane_no); + + float plane_no_proj[3]; + project_plane_normalized_v3_v3v3(plane_no_proj, plane_no, man->data.rotate_axis); + + if (!is_zero_v3(plane_no_proj)) { + const float angle = -angle_signed_on_axis_v3v3_v3(plane_no_proj, man->data.rotate_up, man->data.rotate_axis); + const float angle_delta = angle - angle_compat_rad(value[0], angle); + if (angle_delta != 0.0f) { + float mat[3][3]; + axis_angle_normalized_to_mat3(mat, man->data.rotate_axis, angle_delta); + mul_m3_v3(mat, plane_no); + + /* re-normalize - seems acceptable */ + RNA_property_float_set_array(op->ptr, man->data.prop_axis_no, plane_no); + + manipulator_spin_exec(man); + } + } +} + +/* angle callbacks */ +static void manipulator_spin_prop_angle_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + float *value = value_p; + + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + value[0] = RNA_property_float_get(op->ptr, man->data.prop_angle); +} + +static void manipulator_spin_prop_angle_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + ManipulatorSpinGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + BLI_assert(mpr_prop->type->array_length == 1); + UNUSED_VARS_NDEBUG(mpr_prop); + const float *value = value_p; + RNA_property_float_set(op->ptr, man->data.prop_angle, value[0]); + + manipulator_spin_exec(man); +} + +static bool manipulator_mesh_spin_poll(const bContext *C, wmManipulatorGroupType *wgt) +{ + wmOperator *op = WM_operator_last_redo(C); + if (op == NULL || !STREQ(op->type->idname, "MESH_OT_spin")) { + WM_manipulator_group_type_unlink_delayed_ptr(wgt); + return false; + } + return true; +} + +static void manipulator_mesh_spin_setup(const bContext *C, wmManipulatorGroup *mgroup) +{ + wmOperator *op = WM_operator_last_redo(C); + + if (op == NULL || !STREQ(op->type->idname, "MESH_OT_spin")) { + return; + } + + struct ManipulatorSpinGroup *man = MEM_callocN(sizeof(ManipulatorSpinGroup), __func__); + mgroup->customdata = man; + + const wmManipulatorType *wt_arrow = WM_manipulatortype_find("MANIPULATOR_WT_arrow_3d", true); + const wmManipulatorType *wt_grab = WM_manipulatortype_find("MANIPULATOR_WT_grab_3d", true); + const wmManipulatorType *wt_dial = WM_manipulatortype_find("MANIPULATOR_WT_dial_3d", true); + + man->translate_z = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL); + man->translate_c = WM_manipulator_new_ptr(wt_grab, mgroup, NULL); + man->rotate_c = WM_manipulator_new_ptr(wt_dial, mgroup, NULL); + man->angle_z = WM_manipulator_new_ptr(wt_dial, mgroup, NULL); + + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_z->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, man->translate_c->color); + UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, man->rotate_c->color); + UI_GetThemeColor3fv(TH_AXIS_Z, man->angle_z->color); + + + RNA_enum_set(man->translate_z->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_NORMAL); + RNA_enum_set(man->translate_c->ptr, "draw_style", ED_MANIPULATOR_GRAB_STYLE_RING_2D); + + WM_manipulator_set_flag(man->translate_c, WM_MANIPULATOR_DRAW_VALUE, true); + WM_manipulator_set_flag(man->rotate_c, WM_MANIPULATOR_DRAW_VALUE, true); + WM_manipulator_set_flag(man->angle_z, WM_MANIPULATOR_DRAW_VALUE, true); + + WM_manipulator_set_scale(man->angle_z, 0.5f); + + { + man->data.context = (bContext *)C; + man->data.op = op; + man->data.prop_axis_co = RNA_struct_find_property(op->ptr, "center"); + man->data.prop_axis_no = RNA_struct_find_property(op->ptr, "axis"); + man->data.prop_angle = RNA_struct_find_property(op->ptr, "angle"); + } + + manipulator_mesh_spin_update_from_op(man); + + /* Setup property callbacks */ + { + WM_manipulator_target_property_def_func( + man->translate_z, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_spin_prop_depth_get, + .value_set_fn = manipulator_spin_prop_depth_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->translate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_spin_prop_translate_get, + .value_set_fn = manipulator_spin_prop_translate_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->rotate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_spin_prop_axis_angle_get, + .value_set_fn = manipulator_spin_prop_axis_angle_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_target_property_def_func( + man->angle_z, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_spin_prop_angle_get, + .value_set_fn = manipulator_spin_prop_angle_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + } +} + +static void manipulator_mesh_spin_draw_prepare( + const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + ManipulatorSpinGroup *man = mgroup->customdata; + if (man->data.op->next) { + man->data.op = WM_operator_last_redo((bContext *)man->data.context); + } + manipulator_mesh_spin_update_from_op(man); +} + +static void MESH_WGT_spin(struct wmManipulatorGroupType *wgt) +{ + wgt->name = "Mesh Spin"; + wgt->idname = "MESH_WGT_spin"; + + wgt->flag = WM_MANIPULATORGROUPTYPE_3D; + + wgt->mmap_params.spaceid = SPACE_VIEW3D; + wgt->mmap_params.regionid = RGN_TYPE_WINDOW; + + wgt->poll = manipulator_mesh_spin_poll; + wgt->setup = manipulator_mesh_spin_setup; + wgt->draw_prepare = manipulator_mesh_spin_draw_prepare; +} + +/** \} */ + +#endif /* USE_MANIPULATOR */ + + static int edbm_screw_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 658f8b3958b..c0501078424 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -54,8 +54,10 @@ #include "BKE_editmesh_bvh.h" #include "BKE_report.h" -#include "BIF_gl.h" -#include "BIF_glutil.h" /* for paint cursor */ +#include "DEG_depsgraph.h" + +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -159,6 +161,7 @@ typedef struct KnifePosData { typedef struct KnifeTool_OpData { ARegion *ar; /* region that knifetool was activated in */ void *draw_handle; /* for drawing preview loop */ + EvaluationContext eval_ctx; ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */ float mval[2]; /* mouse value with snapping applied */ //bContext *C; @@ -1004,12 +1007,18 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd) copy_v3_v3(v2, ray_hit_best[1]); } - UI_ThemeColor(TH_TRANSFORM); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_TRANSFORM); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(v1); - glVertex3fv(v2); - glEnd(); + + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immEnd(); + + immUnbindProgram(); } static void knife_init_colors(KnifeColors *colors) @@ -1037,66 +1046,69 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) glPolygonOffset(1.0f, 1.0f); - glPushMatrix(); - glMultMatrixf(kcd->ob->obmat); + gpuPushMatrix(); + gpuMultMatrix(kcd->ob->obmat); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (kcd->mode == MODE_DRAGGING) { if (kcd->is_angle_snapping) knifetool_draw_angle_snapping(kcd); - glColor3ubv(kcd->colors.line); - + immUniformColor3ubv(kcd->colors.line); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(kcd->prev.cage); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, kcd->prev.cage); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->prev.vert) { - glColor3ubv(kcd->colors.point); + immUniformColor3ubv(kcd->colors.point); glPointSize(11); - glBegin(GL_POINTS); - glVertex3fv(kcd->prev.cage); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, kcd->prev.cage); + immEnd(); } if (kcd->prev.bmface) { - glColor3ubv(kcd->colors.curpoint); + immUniformColor3ubv(kcd->colors.curpoint); glPointSize(9); - glBegin(GL_POINTS); - glVertex3fv(kcd->prev.cage); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, kcd->prev.cage); + immEnd(); } if (kcd->curr.edge) { - glColor3ubv(kcd->colors.edge); + immUniformColor3ubv(kcd->colors.edge); glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3fv(kcd->curr.edge->v1->cageco); - glVertex3fv(kcd->curr.edge->v2->cageco); - glEnd(); + immBegin(GWN_PRIM_LINES, 2); + immVertex3fv(pos, kcd->curr.edge->v1->cageco); + immVertex3fv(pos, kcd->curr.edge->v2->cageco); + immEnd(); } else if (kcd->curr.vert) { - glColor3ubv(kcd->colors.point); + immUniformColor3ubv(kcd->colors.point); glPointSize(11); - glBegin(GL_POINTS); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->curr.bmface) { - glColor3ubv(kcd->colors.curpoint); + immUniformColor3ubv(kcd->colors.curpoint); glPointSize(9); - glBegin(GL_POINTS); - glVertex3fv(kcd->curr.cage); - glEnd(); + immBegin(GWN_PRIM_POINTS, 1); + immVertex3fv(pos, kcd->curr.cage); + immEnd(); } if (kcd->totlinehit > 0) { @@ -1107,26 +1119,35 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* draw any snapped verts first */ - glColor4ubv(kcd->colors.point_a); + immUniformColor4ubv(kcd->colors.point_a); glPointSize(11); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, kcd->totlinehit); + lh = kcd->linehits; for (i = 0; i < kcd->totlinehit; i++, lh++) { - if (lh->v) - glVertex3fv(lh->cagehit); + if (lh->v) { + immVertex3fv(pos, lh->cagehit); + } } - glEnd(); + + immEnd(); /* now draw the rest */ - glColor4ubv(kcd->colors.curpoint_a); + immUniformColor4ubv(kcd->colors.curpoint_a); glPointSize(7); - glBegin(GL_POINTS); + + immBeginAtMost(GWN_PRIM_POINTS, kcd->totlinehit); + lh = kcd->linehits; for (i = 0; i < kcd->totlinehit; i++, lh++) { - if (!lh->v) - glVertex3fv(lh->cagehit); + if (!lh->v) { + immVertex3fv(pos, lh->cagehit); + } } - glEnd(); + + immEnd(); + glDisable(GL_BLEND); } @@ -1134,44 +1155,46 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) BLI_mempool_iter iter; KnifeEdge *kfe; + immUniformColor3ubv(kcd->colors.line); glLineWidth(1.0); - glBegin(GL_LINES); + + immBeginAtMost(GWN_PRIM_LINES, BLI_mempool_count(kcd->kedges) * 2); BLI_mempool_iternew(kcd->kedges, &iter); for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) { if (!kfe->is_cut) continue; - glColor3ubv(kcd->colors.line); - - glVertex3fv(kfe->v1->cageco); - glVertex3fv(kfe->v2->cageco); + immVertex3fv(pos, kfe->v1->cageco); + immVertex3fv(pos, kfe->v2->cageco); } - glEnd(); + immEnd(); } if (kcd->totkvert > 0) { BLI_mempool_iter iter; KnifeVert *kfv; + immUniformColor3ubv(kcd->colors.point); glPointSize(5.0); - glBegin(GL_POINTS); + immBeginAtMost(GWN_PRIM_POINTS, BLI_mempool_count(kcd->kverts)); + BLI_mempool_iternew(kcd->kverts, &iter); for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) { if (!kfv->is_cut) continue; - glColor3ubv(kcd->colors.point); - - glVertex3fv(kfv->cageco); + immVertex3fv(pos, kfv->cageco); } - glEnd(); + immEnd(); } - glPopMatrix(); + immUnbindProgram(); + + gpuPopMatrix(); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -1394,7 +1417,7 @@ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data) * intersecting faces matching this face (or connected when an vert/edge) will be ignored. */ static bool point_is_visible( - KnifeTool_OpData *kcd, const float p[3], const float s[2], bglMats *mats, + KnifeTool_OpData *kcd, const float p[3], const float s[2], BMElem *ele_test) { BMFace *f_hit; @@ -1412,7 +1435,7 @@ static bool point_is_visible( float view[3], p_ofs[3]; /* TODO: I think there's a simpler way to get the required raycast ray */ - ED_view3d_unproject(mats, view, s[0], s[1], 0.0f); + ED_view3d_unproject(kcd->vc.ar, s[0], s[1], 0.0f, view); mul_m4_v3(kcd->ob->imat, view); @@ -1485,7 +1508,6 @@ static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh) /* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */ static void knife_find_line_hits(KnifeTool_OpData *kcd) { - bglMats mats; SmallHash faces, kfes, kfvs; float v1[3], v2[3], v3[3], v4[3], s1[2], s2[2]; BVHTree *planetree, *tree; @@ -1515,8 +1537,6 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) const bool use_hit_prev = true; const bool use_hit_curr = (kcd->is_drag_hold == false); - bgl_get_mats(&mats); - if (kcd->linehits) { MEM_freeN(kcd->linehits); kcd->linehits = NULL; @@ -1645,7 +1665,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) knife_project_v2(kcd, v->cageco, s); d = dist_squared_to_line_segment_v2(s, s1, s2); if ((d <= vert_tol_sq) && - (point_is_visible(kcd, v->cageco, s, &mats, bm_elem_from_knife_vert(v, &kfe_hit)))) + (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit)))) { memset(&hit, 0, sizeof(hit)); hit.v = v; @@ -1708,7 +1728,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) * Need to find 3d intersection of ray through sint */ knife_input_ray_segment(kcd, sint, 1.0f, r1, r2); isect_kind = isect_line_line_v3(kfe->v1->cageco, kfe->v2->cageco, r1, r2, p_cage, p_cage_tmp); - if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats, bm_elem_from_knife_edge(kfe))) { + if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, bm_elem_from_knife_edge(kfe))) { memset(&hit, 0, sizeof(hit)); if (kcd->snap_midpoints) { /* choose intermediate point snap too */ @@ -1737,7 +1757,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) float p[3], p_cage[3]; if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) { - if (point_is_visible(kcd, p_cage, s1, &mats, (BMElem *)f)) { + if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) { memset(&hit, 0, sizeof(hit)); hit.f = f; copy_v3_v3(hit.hit, p); @@ -1749,7 +1769,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) } if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) { - if (point_is_visible(kcd, p_cage, s2, &mats, (BMElem *)f)) { + if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) { memset(&hit, 0, sizeof(hit)); hit.f = f; copy_v3_v3(hit.hit, p); @@ -1782,13 +1802,9 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs, float r_origin[3], float r_origin_ofs[3]) { - bglMats mats; - - bgl_get_mats(&mats); - /* unproject to find view ray */ - ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); - ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs); + ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], 0.0f, r_origin); + ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], ofs, r_origin_ofs); /* transform into object space */ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); @@ -1822,7 +1838,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float if (!f) { if (kcd->is_interactive) { /* try to use backbuffer selection method if ray casting failed */ - f = EDBM_face_find_nearest(&kcd->vc, &dist); + f = EDBM_face_find_nearest(&kcd->eval_ctx, &kcd->vc, &dist); /* cheat for now; just put in the origin instead * of a true coordinate on the face. @@ -2574,7 +2590,7 @@ static void knifetool_init_bmbvh(KnifeTool_OpData *kcd) { BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT); - kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, kcd->scene, NULL); + kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(&kcd->eval_ctx, kcd->em, kcd->scene, NULL); kcd->bmbvh = BKE_bmbvh_new_from_editmesh( kcd->em, @@ -2608,6 +2624,7 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd, kcd->ob = obedit; kcd->ar = CTX_wm_region(C); + CTX_data_eval_ctx(C, &kcd->eval_ctx); em_setup_viewcontext(C, &kcd->vc); kcd->em = BKE_editmesh_from_object(kcd->ob); @@ -2775,6 +2792,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } + CTX_data_eval_ctx(C, &kcd->eval_ctx); em_setup_viewcontext(C, &kcd->vc); kcd->ar = kcd->vc.ar; @@ -3008,7 +3026,6 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2]) void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through) { KnifeTool_OpData *kcd; - bglMats mats; view3d_operator_needs_opengl(C); @@ -3027,10 +3044,6 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug if (use_tag) { BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false); } - - if (kcd->cut_through == false) { - bgl_get_mats(&mats); - } } /* execute */ @@ -3139,7 +3152,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug float cent[3], cent_ss[2]; BM_face_calc_point_in_face(f, cent); knife_project_v2(kcd, cent, cent_ss); - if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats, (BMElem *)f)) && + if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) && edbm_mesh_knife_point_isect(polys, cent_ss)) { BM_elem_flag_enable(f, BM_ELEM_TAG); diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index 0d3cc07589b..c98d22503e1 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -42,6 +42,8 @@ #include "BKE_editmesh.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "RNA_define.h" #include "RNA_access.h" @@ -56,13 +58,17 @@ #include "mesh_intern.h" /* own include */ -static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object *ob, LinkNode *polys) +static LinkNode *knifeproject_poly_from_object(const bContext *C, Scene *scene, Object *ob, LinkNode *polys) { + ARegion *ar = CTX_wm_region(C); + EvaluationContext eval_ctx; DerivedMesh *dm; bool dm_needsFree; + CTX_data_eval_ctx(C, &eval_ctx); + if (ob->type == OB_MESH || ob->derivedFinal) { - dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(&eval_ctx, scene, ob, CD_MASK_BAREMESH); dm_needsFree = false; } else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { @@ -116,7 +122,6 @@ static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object static int knifeproject_exec(bContext *C, wmOperator *op) { - ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -127,7 +132,7 @@ static int knifeproject_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { if (ob != obedit) { - polys = knifeproject_poly_from_object(ar, scene, ob, polys); + polys = knifeproject_poly_from_object(C, scene, ob, polys); } } CTX_DATA_END; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index f1c1e4105d0..a4a6ad82dfb 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -45,7 +45,8 @@ #include "BKE_DerivedMesh.h" #include "BKE_unit.h" -#include "BIF_gl.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" #include "UI_interface.h" @@ -62,6 +63,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "DEG_depsgraph.h" + #include "mesh_intern.h" /* own include */ #define SUBD_SMOOTH_MAX 4.0f @@ -104,27 +107,41 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) if (v3d && v3d->zbuf) glDisable(GL_DEPTH_TEST); - glPushMatrix(); - glMultMatrixf(lcd->ob->obmat); + gpuPushMatrix(); + gpuMultMatrix(lcd->ob->obmat); + + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ub(255, 0, 255); - glColor3ub(255, 0, 255); if (lcd->totedge > 0) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, lcd->edges); - glDrawArrays(GL_LINES, 0, lcd->totedge * 2); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_LINES, lcd->totedge * 2); + + for (int i = 0; i < lcd->totedge; i++) { + immVertex3fv(pos, lcd->edges[i][0]); + immVertex3fv(pos, lcd->edges[i][1]); + } + + immEnd(); } if (lcd->totpoint > 0) { glPointSize(3.0f); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, lcd->points); - glDrawArrays(GL_POINTS, 0, lcd->totpoint); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(GWN_PRIM_POINTS, lcd->totpoint); + + for (int i = 0; i < lcd->totpoint; i++) { + immVertex3fv(pos, lcd->points[i]); + } + + immEnd(); } - glPopMatrix(); + immUnbindProgram(); + + gpuPopMatrix(); + if (v3d && v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -541,20 +558,23 @@ static void loopcut_update_edge(RingSelOpData *lcd, BMEdge *e, const int preview } } -static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines) +static void loopcut_mouse_move(const struct EvaluationContext *eval_ctx, RingSelOpData *lcd, const int previewlines) { float dist = ED_view3d_select_dist_px(); - BMEdge *e = EDBM_edge_find_nearest(&lcd->vc, &dist); + BMEdge *e = EDBM_edge_find_nearest(eval_ctx, &lcd->vc, &dist); loopcut_update_edge(lcd, e, previewlines); } /* called by both init() and exec() */ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) { + EvaluationContext eval_ctx; const bool is_interactive = (event != NULL); Object *obedit = CTX_data_edit_object(C); RingSelOpData *lcd; + CTX_data_eval_ctx(C, &eval_ctx); + if (modifiers_isDeformedByLattice(obedit) || modifiers_isDeformedByArmature(obedit)) BKE_report(op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display"); @@ -582,7 +602,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) if (is_interactive) { copy_v2_v2_int(lcd->vc.mval, event->mval); - loopcut_mouse_move(lcd, is_interactive ? 1 : 0); + loopcut_mouse_move(&eval_ctx, lcd, is_interactive ? 1 : 0); } else { const int e_index = RNA_int_get(op->ptr, "edge_index"); @@ -655,12 +675,14 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op) static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) { + EvaluationContext eval_ctx; RingSelOpData *lcd = op->customdata; float cuts = lcd->cuts; float smoothness = lcd->smoothness; bool show_cuts = false; const bool has_numinput = hasNumInput(&lcd->num); + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &lcd->vc); lcd->ar = lcd->vc.ar; @@ -746,7 +768,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) if (!has_numinput) { lcd->vc.mval[0] = event->mval[0]; lcd->vc.mval[1] = event->mval[1]; - loopcut_mouse_move(lcd, (int)lcd->cuts); + loopcut_mouse_move(&eval_ctx, lcd, (int)lcd->cuts); ED_region_tag_redraw(lcd->ar); handled = true; diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index a85d2425b3c..b71dd029bf2 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -59,6 +59,8 @@ #include "bmesh.h" #include "bmesh_tools.h" +#include "DEG_depsgraph.h" + #include "mesh_intern.h" /* own include */ struct PathSelectParams { @@ -570,19 +572,19 @@ static bool edbm_shortest_path_pick_ex( static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op); -static BMElem *edbm_elem_find_nearest(ViewContext *vc, const char htype) +static BMElem *edbm_elem_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, const char htype) { BMEditMesh *em = vc->em; float dist = ED_view3d_select_dist_px(); if ((em->selectmode & SCE_SELECT_VERTEX) && (htype == BM_VERT)) { - return (BMElem *)EDBM_vert_find_nearest(vc, &dist); + return (BMElem *)EDBM_vert_find_nearest(eval_ctx, vc, &dist); } else if ((em->selectmode & SCE_SELECT_EDGE) && (htype == BM_EDGE)) { - return (BMElem *)EDBM_edge_find_nearest(vc, &dist); + return (BMElem *)EDBM_edge_find_nearest(eval_ctx, vc, &dist); } else if ((em->selectmode & SCE_SELECT_FACE) && (htype == BM_FACE)) { - return (BMElem *)EDBM_face_find_nearest(vc, &dist); + return (BMElem *)EDBM_face_find_nearest(eval_ctx, vc, &dist); } return NULL; @@ -605,10 +607,12 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE return edbm_shortest_path_pick_exec(C, op); } + EvaluationContext eval_ctx; ViewContext vc; BMEditMesh *em; bool track_active = true; + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, event->mval); em = vc.em; @@ -617,14 +621,14 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE BMElem *ele_src, *ele_dst; if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) || - !(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype))) + !(ele_dst = edbm_elem_find_nearest(&eval_ctx, &vc, ele_src->head.htype))) { /* special case, toggle edge tags even when we don't have a path */ if (((em->selectmode & SCE_SELECT_EDGE) && (vc.scene->toolsettings->edge_mode != EDGE_MODE_SELECT)) && /* check if we only have a destination edge */ ((ele_src == NULL) && - (ele_dst = edbm_elem_find_nearest(&vc, BM_EDGE)))) + (ele_dst = edbm_elem_find_nearest(&eval_ctx, &vc, BM_EDGE)))) { ele_src = ele_dst; track_active = false; diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c new file mode 100644 index 00000000000..bfabd64396f --- /dev/null +++ b/source/blender/editors/mesh/editmesh_polybuild.c @@ -0,0 +1,541 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mesh/editmesh_polybuild.c + * \ingroup edmesh + * + * Tools to implement polygon building tool, + * an experimental tool for quickly constructing/manipulating faces. + */ + +#include "DNA_object_types.h" + +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_editmesh.h" +#include "BKE_mesh.h" + +#include "WM_types.h" + +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_transform.h" +#include "ED_view3d.h" + +#include "bmesh.h" + +#include "mesh_intern.h" /* own include */ + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" + +/* -------------------------------------------------------------------- */ +/** \name Local Utilities + * \{ */ + +static void edbm_selectmode_ensure(Scene *scene, BMEditMesh *em, short selectmode) +{ + if ((scene->toolsettings->selectmode & selectmode) == 0) { + scene->toolsettings->selectmode |= selectmode; + em->selectmode = scene->toolsettings->selectmode; + EDBM_selectmode_set(em); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Face At Cursor + * \{ */ + +static int edbm_polybuild_face_at_cursor_invoke( + bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ViewContext vc; + float center[3]; + bool changed = false; + + em_setup_viewcontext(C, &vc); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + BMElem *ele_act = BM_mesh_active_elem_get(bm); + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); + + if (ele_act == NULL || ele_act->head.htype == BM_FACE) { + /* Just add vert */ + copy_v3_v3(center, ED_view3d_cursor3d_get(vc.scene, vc.v3d)); + mul_v3_m4v3(center, vc.obedit->obmat, center); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_new, true); + changed = true; + } + else if (ele_act->head.htype == BM_EDGE) { + BMEdge *e_act = (BMEdge *)ele_act; + BMFace *f_reference = e_act->l ? e_act->l->f : NULL; + + mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co); + mul_m4_v3(vc.obedit->obmat, center); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + BMVert *v_tri[3]; + v_tri[0] = e_act->v1; + v_tri[1] = e_act->v2; + v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + if (e_act->l && e_act->l->v == v_tri[0]) { + SWAP(BMVert *, v_tri[0], v_tri[1]); + } + // BMFace *f_new = + BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true); + + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_tri[2], true); + changed = true; + } + else if (ele_act->head.htype == BM_VERT) { + BMVert *v_act = (BMVert *)ele_act; + BMEdge *e_pair[2] = {NULL}; + + if (v_act->e != NULL) { + for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) { + int i = 0; + BMEdge *e_iter = v_act->e; + do { + if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) && + (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter))) + { + if (i == 2) { + e_pair[0] = e_pair[1] = NULL; + break; + } + e_pair[i++] = e_iter; + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e); + } + } + + if (e_pair[1] != NULL) { + /* Quad from edge pair. */ + if (BM_edge_calc_length_squared(e_pair[0]) < + BM_edge_calc_length_squared(e_pair[1])) + { + SWAP(BMEdge *, e_pair[0], e_pair[1]); + } + + BMFace *f_reference = e_pair[0]->l ? e_pair[0]->l->f : NULL; + + mul_v3_m4v3(center, vc.obedit->obmat, v_act->co); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + BMVert *v_quad[4]; + v_quad[0] = v_act; + v_quad[1] = BM_edge_other_vert(e_pair[0], v_act); + v_quad[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + v_quad[3] = BM_edge_other_vert(e_pair[1], v_act); + if (e_pair[0]->l && e_pair[0]->l->v == v_quad[0]) { + SWAP(BMVert *, v_quad[1], v_quad[3]); + } + // BMFace *f_new = + BM_face_create_verts(bm, v_quad, 4, f_reference, BM_CREATE_NOP, true); + + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_quad[2], true); + changed = true; + } + else { + /* Just add edge */ + mul_m4_v3(vc.obedit->obmat, center); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, v_act->co, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + BMVert *v_new = BM_vert_create(bm, center, NULL, BM_CREATE_NOP); + + BM_edge_create(bm, v_act, v_new, NULL, BM_CREATE_NOP); + + BM_vert_select_set(bm, v_new, true); + } + } + + if (changed) { + BM_select_history_clear(bm); + + EDBM_mesh_normals_update(em); + EDBM_update_generic(em, true, true); + + WM_event_add_mousemove(C); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Face At Cursor"; + ot->idname = "MESH_OT_polybuild_face_at_cursor"; + ot->description = ""; + + /* api callbacks */ + ot->invoke = edbm_polybuild_face_at_cursor_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* to give to transform */ + Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Split At Cursor + * \{ */ + +static int edbm_polybuild_split_at_cursor_invoke( + bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ViewContext vc; + float center[3]; + bool changed = false; + + em_setup_viewcontext(C, &vc); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); + + BMElem *ele_act = BM_mesh_active_elem_get(bm); + + if (ele_act == NULL || ele_act->head.hflag == BM_FACE) { + return OPERATOR_PASS_THROUGH; + } + else if (ele_act->head.htype == BM_EDGE) { + BMEdge *e_act = (BMEdge *)ele_act; + mid_v3_v3v3(center, e_act->v1->co, e_act->v2->co); + mul_m4_v3(vc.obedit->obmat, center); + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center); + mul_m4_v3(vc.obedit->imat, center); + + const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co); + BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f)); + copy_v3_v3(v_new->co, center); + + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_vert_select_set(bm, v_new, true); + changed = true; + } + else if (ele_act->head.htype == BM_VERT) { + /* Just do nothing, allow dragging. */ + return OPERATOR_FINISHED; + } + + if (changed) { + BM_select_history_clear(bm); + + EDBM_mesh_normals_update(em); + EDBM_update_generic(em, true, true); + + WM_event_add_mousemove(C); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_split_at_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Split At Cursor"; + ot->idname = "MESH_OT_polybuild_split_at_cursor"; + ot->description = ""; + + /* api callbacks */ + ot->invoke = edbm_polybuild_split_at_cursor_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* to give to transform */ + Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ +/** \name Dissolve At Cursor + * + * \{ */ + +static int edbm_polybuild_dissolve_at_cursor_invoke( + bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + ViewContext vc; + em_setup_viewcontext(C, &vc); + bool changed = false; + + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + BMVert *v_act = BM_mesh_active_vert_get(bm); + BMEdge *e_act = BM_mesh_active_edge_get(bm); + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX); + + + if (e_act) { + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(e_act, &l_a, &l_b)) { + BMFace *f_new = BM_faces_join_pair(bm, l_a, l_b, true); + if (f_new) { + changed = true; + } + } + } + else if (v_act) { + if (BM_vert_is_edge_pair(v_act)) { + BM_edge_collapse( + bm, v_act->e, v_act, + true, true); + } + else { + /* too involved to do inline */ + if (!EDBM_op_callf(em, op, + "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", + BM_ELEM_SELECT, false, true)) + { + return OPERATOR_CANCELLED; + } + } + changed = true; + } + + if (changed) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + + BM_select_history_clear(bm); + + EDBM_mesh_normals_update(em); + EDBM_update_generic(em, true, true); + + WM_event_add_mousemove(C); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_dissolve_at_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Dissolve At Cursor"; + ot->idname = "MESH_OT_polybuild_dissolve_at_cursor"; + ot->description = ""; + + /* api callbacks */ + ot->invoke = edbm_polybuild_dissolve_at_cursor_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cursor Manipulator + * + * \note This may need its own file, for now not. + * \{ */ + +static BMElem *edbm_hover_preselect( + bContext *C, + const int mval[2], + bool use_boundary) +{ + ViewContext vc; + + em_setup_viewcontext(C, &vc); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + + invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + const float mval_fl[2] = {UNPACK2(mval)}; + float ray_origin[3], ray_direction[3]; + + BMElem *ele_best = NULL; + + if (ED_view3d_win_to_ray( + vc.ar, vc.v3d, mval_fl, + ray_origin, ray_direction, true)) + { + BMEdge *e; + + BMIter eiter; + float dist_sq_best = FLT_MAX; + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) && + (!use_boundary || BM_edge_is_boundary(e))) + { + float dist_sq_test; + float point[3]; + float depth; +#if 0 + dist_sq_test = dist_squared_ray_to_seg_v3( + ray_origin, ray_direction, + e->v1->co, e->v2->co, + point, &depth); +#else + mid_v3_v3v3(point, e->v1->co, e->v2->co); + dist_sq_test = dist_squared_to_ray_v3( + ray_origin, ray_direction, + point, &depth); +#endif + + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + ele_best = (BMElem *)e; + } + + dist_sq_test = dist_squared_to_ray_v3( + ray_origin, ray_direction, + e->v1->co, &depth); + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + ele_best = (BMElem *)e->v1; + } + dist_sq_test = dist_squared_to_ray_v3( + ray_origin, ray_direction, + e->v2->co, &depth); + if (dist_sq_test < dist_sq_best) { + dist_sq_best = dist_sq_test; + ele_best = (BMElem *)e->v2; + } + } + } + } + return ele_best; +} + +/* + * Developer note: this is not advocating pre-selection highlighting. + * This is just a quick way to test how a tool for interactively editing polygons may work. */ +static int edbm_polybuild_hover_invoke( + bContext *C, wmOperator *op, const wmEvent *event) +{ + const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary"); + ViewContext vc; + + em_setup_viewcontext(C, &vc); + + /* Vertex selection is needed */ + if ((vc.scene->toolsettings->selectmode & SCE_SELECT_VERTEX) == 0) { + return OPERATOR_PASS_THROUGH; + } + + /* Don't overwrite click-drag events. */ + if (use_boundary == false) { + /* pass */ + } + else if (vc.win->tweak || + (vc.win->eventstate->check_click && + vc.win->eventstate->prevval == KM_PRESS && + ISMOUSE(vc.win->eventstate->prevtype))) + { + return OPERATOR_PASS_THROUGH; + } + + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + BMElem *ele_active = BM_mesh_active_elem_get(bm); + BMElem *ele_hover = edbm_hover_preselect(C, event->mval, use_boundary); + + if (ele_hover && (ele_hover != ele_active)) { + if (event->shift == 0) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_select_history_clear(bm); + } + BM_elem_select_set(bm, ele_hover, true); + BM_select_history_store(em->bm, ele_hover); + BKE_mesh_batch_cache_dirty(obedit->data, BKE_MESH_BATCH_DIRTY_SELECT); + + ED_region_tag_redraw(vc.ar); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_polybuild_hover(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Poly Build Hover"; + ot->idname = "MESH_OT_polybuild_hover"; + ot->description = ""; + + /* api callbacks */ + ot->invoke = edbm_polybuild_hover_invoke; + ot->poll = EDBM_view3d_poll; + + /* flags */ + ot->flag = OPTYPE_INTERNAL; + + /* properties */ + RNA_def_boolean(ot->srna, "use_boundary", false, "Boundary", "Select only boundary geometry"); +} + +/** \} */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 3f443b49a5e..0a0a8ff2de3 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -68,6 +68,8 @@ #include "bmesh_tools.h" +#include "DEG_depsgraph.h" + #include "mesh_intern.h" /* own include */ /* use bmesh operator flags for a few operators */ @@ -194,7 +196,9 @@ static BLI_bitmap *edbm_backbuf_alloc(const int size) /* reads rect, and builds selection array for quick lookup */ /* returns if all is OK */ -bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) +bool EDBM_backbuf_border_init( + const struct EvaluationContext *eval_ctx, ViewContext *vc, short xmin, + short ymin, short xmax, short ymax) { struct ImBuf *buf; unsigned int *dr; @@ -204,7 +208,7 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma return false; } - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } @@ -267,7 +271,7 @@ static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data) * - grab again and compare * returns 'OK' */ -bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) +bool EDBM_backbuf_border_mask_init(const struct EvaluationContext *eval_ctx, ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) { unsigned int *dr, *dr_mask, *dr_mask_arr; struct ImBuf *buf; @@ -284,7 +288,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short return false; } - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } @@ -317,7 +321,9 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short } /* circle shaped sample area */ -bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) +bool EDBM_backbuf_circle_init( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + short xs, short ys, short rads) { struct ImBuf *buf; unsigned int *dr; @@ -336,7 +342,7 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) xmin = xs - rads; xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; - buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(eval_ctx, vc, xmin, ymin, xmax, ymax); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; } @@ -435,7 +441,7 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float * \param use_cycle Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index. */ BMVert *EDBM_vert_find_nearest_ex( - ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist, const bool use_select_bias, bool use_cycle) { BMesh *bm = vc->em->bm; @@ -447,10 +453,10 @@ BMVert *EDBM_vert_find_nearest_ex( BMVert *eve; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); index = ED_view3d_backbuf_sample_rect( - vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); + eval_ctx, vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; if (eve) { @@ -485,7 +491,7 @@ BMVert *EDBM_vert_find_nearest_ex( data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); + mesh_foreachScreenVert(eval_ctx, vc, findnearestvert__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; *r_dist = hit->dist; @@ -497,9 +503,9 @@ BMVert *EDBM_vert_find_nearest_ex( } } -BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) +BMVert *EDBM_vert_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist) { - return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); + return EDBM_vert_find_nearest_ex(eval_ctx, vc, r_dist, false, false); } /* find the distance to the edge we already have */ @@ -621,7 +627,7 @@ static void find_nearest_edge__doClosest( } BMEdge *EDBM_edge_find_nearest_ex( - ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist, float *r_dist_center, const bool use_select_bias, const bool use_cycle, BMEdge **r_eed_zbuf) @@ -635,9 +641,9 @@ BMEdge *EDBM_edge_find_nearest_ex( BMEdge *eed; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); - index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); + index = ED_view3d_backbuf_sample_rect(eval_ctx, vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; if (r_eed_zbuf) { @@ -655,7 +661,7 @@ BMEdge *EDBM_edge_find_nearest_ex( ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenEdge(eval_ctx, vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); *r_dist_center = data.dist; } @@ -695,7 +701,7 @@ BMEdge *EDBM_edge_find_nearest_ex( data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); + mesh_foreachScreenEdge(eval_ctx, vc, find_nearest_edge__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; *r_dist = hit->dist; @@ -711,9 +717,9 @@ BMEdge *EDBM_edge_find_nearest_ex( } BMEdge *EDBM_edge_find_nearest( - ViewContext *vc, float *r_dist) + const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist) { - return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); + return EDBM_edge_find_nearest_ex(eval_ctx, vc, r_dist, NULL, false, false, NULL); } /* find the distance to the face we already have */ @@ -787,7 +793,7 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, const float BMFace *EDBM_face_find_nearest_ex( - ViewContext *vc, float *r_dist, + const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist, float *r_dist_center, const bool use_select_bias, const bool use_cycle, BMFace **r_efa_zbuf) @@ -799,9 +805,9 @@ BMFace *EDBM_face_find_nearest_ex( unsigned int index; BMFace *efa; - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); - index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); + index = ED_view3d_backbuf_sample(eval_ctx, vc, vc->mval[0], vc->mval[1]); efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; if (r_efa_zbuf) { @@ -819,7 +825,7 @@ BMFace *EDBM_face_find_nearest_ex( ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(eval_ctx, vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); *r_dist_center = data.dist; } @@ -857,7 +863,7 @@ BMFace *EDBM_face_find_nearest_ex( data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); + mesh_foreachScreenFace(eval_ctx, vc, findnearestface__doClosest, &data, clip_flag); hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; *r_dist = hit->dist; @@ -872,9 +878,9 @@ BMFace *EDBM_face_find_nearest_ex( } } -BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) +BMFace *EDBM_face_find_nearest(const struct EvaluationContext *eval_ctx, ViewContext *vc, float *r_dist) { - return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); + return EDBM_face_find_nearest_ex(eval_ctx, vc, r_dist, NULL, false, false, NULL); } #undef FIND_NEAR_SELECT_BIAS @@ -886,7 +892,9 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) * selected vertices and edges get disadvantage * return 1 if found one */ -static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) +static int unified_findnearest( + const struct EvaluationContext *eval_ctx, ViewContext *vc, + BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) { BMEditMesh *em = vc->em; static short mval_prev[2] = {-1, -1}; @@ -905,12 +913,12 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ - ED_view3d_backbuf_validate(vc); + ED_view3d_backbuf_validate(eval_ctx, vc); if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { float dist_center = 0.0f; float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL; - efa = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); + efa = EDBM_face_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); if (efa && dist_center_p) { dist = min_ff(dist_margin, dist_center); } @@ -919,14 +927,14 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { float dist_center = 0.0f; float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; - eed = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); + eed = EDBM_edge_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); if (eed && dist_center_p) { dist = min_ff(dist_margin, dist_center); } } if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { - eve = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle); + eve = EDBM_vert_find_nearest_ex(eval_ctx, vc, &dist, true, use_cycle); } /* return only one of 3 pointers, for frontbuffer redraws */ @@ -989,13 +997,13 @@ static const EnumPropertyItem prop_similar_types[] = { #endif {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""}, - {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""}, {SIMFACE_AREA, "AREA", 0, "Area", ""}, {SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""}, {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""}, {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""}, {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""}, {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""}, + {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""}, #ifdef WITH_FREESTYLE {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""}, #endif @@ -1173,7 +1181,7 @@ static const EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA #ifdef WITH_FREESTYLE const int a_end = SIMFACE_FREESTYLE; #else - const int a_end = SIMFACE_SMOOTH; + const int a_end = SIMFACE_FACEMAP; #endif for (a = SIMFACE_MATERIAL; a <= a_end; a++) { RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a); @@ -1559,6 +1567,7 @@ static void mouse_mesh_loop_edge(BMEditMesh *em, BMEdge *eed, bool select, bool static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring) { + EvaluationContext eval_ctx; ViewContext vc; BMEditMesh *em; BMEdge *eed; @@ -1568,15 +1577,16 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de float dist = ED_view3d_select_dist_px() * 0.6666f; float mvalf[2]; + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &vc); mvalf[0] = (float)(vc.mval[0] = mval[0]); mvalf[1] = (float)(vc.mval[1] = mval[1]); em = vc.em; /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */ - ED_view3d_backbuf_validate(&vc); + ED_view3d_backbuf_validate(&eval_ctx, &vc); - eed = EDBM_edge_find_nearest_ex(&vc, &dist, NULL, true, true, NULL); + eed = EDBM_edge_find_nearest_ex(&eval_ctx, &vc, &dist, NULL, true, true, NULL); if (eed == NULL) { return false; } @@ -1819,17 +1829,19 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot) /* gets called via generic mouse select operator */ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) { + EvaluationContext eval_ctx; ViewContext vc; BMVert *eve = NULL; BMEdge *eed = NULL; BMFace *efa = NULL; /* setup view context for argument to callbacks */ + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &vc); vc.mval[0] = mval[0]; vc.mval[1] = mval[1]; - if (unified_findnearest(&vc, &eve, &eed, &efa)) { + if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa)) { /* Deselect everything */ if (extend == false && deselect == false && toggle == false) @@ -1916,12 +1928,30 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect EDBM_selectmode_flush(vc.em); - /* change active material on object */ - if (efa && efa->mat_nr != vc.obedit->actcol - 1) { - vc.obedit->actcol = efa->mat_nr + 1; - vc.em->mat_nr = efa->mat_nr; + if (efa) { + /* Change active material on object. */ + if (efa->mat_nr != vc.obedit->actcol - 1) { + vc.obedit->actcol = efa->mat_nr + 1; + vc.em->mat_nr = efa->mat_nr; + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); + } - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); + /* Change active face-map on object. */ + if (!BLI_listbase_is_empty(&vc.obedit->fmaps)) { + const int cd_fmap_offset = CustomData_get_offset(&vc.em->bm->pdata, CD_FACEMAP); + if (cd_fmap_offset != -1) { + int map = *((int *)BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset)); + if ((map < -1) || (map > BLI_listbase_count_ex(&vc.obedit->fmaps, map))) { + map = -1; + } + map += 1; + if (map != vc.obedit->actfmap) { + /* We may want to add notifiers later, + * currently select update handles redraw. */ + vc.obedit->actfmap = map; + } + } + } } @@ -2775,6 +2805,7 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); + EvaluationContext eval_ctx; ViewContext vc; BMEditMesh *em; BMesh *bm; @@ -2792,6 +2823,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE view3d_operator_needs_opengl(C); /* setup view context for argument to callbacks */ + CTX_data_eval_ctx(C, &eval_ctx); em_setup_viewcontext(C, &vc); em = vc.em; bm = em->bm; @@ -2804,7 +2836,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE vc.mval[1] = event->mval[1]; /* return warning! */ - if (unified_findnearest(&vc, &eve, &eed, &efa) == 0) { + if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa) == 0) { WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index bf25f7ee7d1..aff82cd1204 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -47,15 +47,18 @@ #include "BLI_rand.h" #include "BLI_sort_utils.h" +#include "BKE_layer.h" #include "BKE_material.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_report.h" #include "BKE_texture.h" #include "BKE_main.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "BLT_translation.h" #include "RNA_define.h" @@ -306,7 +309,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) ED_view3d_init_mats_rv3d(obedit, ar->regiondata); struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), 0, + CTX_data_main(C), CTX_data_scene(C), CTX_data_scene_layer(C), CTX_data_engine(C), 0, ar, CTX_wm_view3d(C)); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -2448,7 +2451,7 @@ static void shape_propagate(BMEditMesh *em, wmOperator *op) //TAG Mesh Objects that share this data for (base = scene->base.first; base; base = base->next) { if (base->object && base->object->data == me) { - DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); + DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } } #endif @@ -3011,7 +3014,7 @@ enum { MESH_SEPARATE_LOOSE = 2, }; -static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static Base *mesh_separate_tagged(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { Base *base_new; Object *obedit = base_old->object; @@ -3032,11 +3035,11 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE); - base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH); + base_new = ED_object_add_duplicate(bmain, scene, sl, base_old, USER_DUP_MESH); /* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */ assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */ - ED_base_object_select(base_new, BA_SELECT); + ED_object_base_select(base_new, BA_SELECT); BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "duplicate geom=%hvef dest=%p", BM_ELEM_TAG, bm_new); @@ -3058,7 +3061,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe return base_new; } -static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_selected(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { /* we may have tags from previous operators */ BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false); @@ -3066,7 +3069,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM /* sel -> tag */ BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT); - return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL); + return (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL); } /* flush a hflag to from verts to edges/faces */ @@ -3165,7 +3168,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const } } -static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_material(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { BMFace *f_cmp, *f; BMIter iter; @@ -3206,7 +3209,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM } /* Move selection into a separate object */ - base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old); + base_new = mesh_separate_tagged(bmain, scene, sl, base_old, bm_old); if (base_new) { mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr); } @@ -3217,7 +3220,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM return result; } -static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) +static bool mesh_separate_loose(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old) { int i; BMEdge *e; @@ -3270,7 +3273,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG); /* Move selection into a separate object */ - result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL); + result |= (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL); } return result; @@ -3280,6 +3283,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); const int type = RNA_enum_get(op->ptr, "type"); int retval = 0; @@ -3300,13 +3304,13 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) /* editmode separate */ switch (type) { case MESH_SEPARATE_SELECTED: - retval = mesh_separate_selected(bmain, scene, base, em->bm); + retval = mesh_separate_selected(bmain, scene, sl, base, em->bm); break; case MESH_SEPARATE_MATERIAL: - retval = mesh_separate_material(bmain, scene, base, em->bm); + retval = mesh_separate_material(bmain, scene, sl, base, em->bm); break; case MESH_SEPARATE_LOOSE: - retval = mesh_separate_loose(bmain, scene, base, em->bm); + retval = mesh_separate_loose(bmain, scene, sl, base, em->bm); break; default: BLI_assert(0); @@ -3341,10 +3345,10 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) switch (type) { case MESH_SEPARATE_MATERIAL: - retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old); + retval_iter = mesh_separate_material(bmain, scene, sl, base_iter, bm_old); break; case MESH_SEPARATE_LOOSE: - retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old); + retval_iter = mesh_separate_loose(bmain, scene, sl, base_iter, bm_old); break; default: BLI_assert(0); @@ -3354,7 +3358,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) if (retval_iter) { BM_mesh_bm_to_me(bm_old, me, (&(struct BMeshToMeshParams){0})); - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); } @@ -3369,7 +3373,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) if (retval) { /* delay depsgraph recalc until all objects are duplicated */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); return OPERATOR_FINISHED; @@ -5060,7 +5064,7 @@ static void sort_bmelem_flag(Scene *scene, Object *ob, } BM_mesh_remap(em->bm, map[0], map[1], map[2]); -/* DAG_id_tag_update(ob->data, 0);*/ +/* DEG_id_tag_update(ob->data, 0);*/ for (j = 3; j--; ) { if (map[j]) @@ -5887,7 +5891,7 @@ static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(obedit->data, OB_RECALC_DATA); + DEG_id_tag_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -5951,7 +5955,7 @@ static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update(obedit->data, OB_RECALC_DATA); + DEG_id_tag_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index c8151862b6c..eb3fea24cc1 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -44,7 +44,6 @@ #include "BKE_DerivedMesh.h" #include "BKE_context.h" #include "BKE_global.h" -#include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" @@ -52,6 +51,8 @@ #include "BKE_editmesh.h" #include "BKE_editmesh_bvh.h" +#include "DEG_depsgraph.h" + #include "BKE_object.h" /* XXX. only for EDBM_mesh_ensure_valid_dm_hack() which will be removed */ #include "WM_api.h" @@ -116,7 +117,7 @@ void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em) { /* since we may not have done selection flushing */ if ((em->ob->recalc & OB_RECALC_DATA) == 0) { - DAG_id_tag_update(&em->ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&em->ob->id, OB_RECALC_DATA); } BKE_object_handle_update(G.main->eval_ctx, scene, em->ob); } @@ -382,7 +383,7 @@ void EDBM_mesh_make(ToolSettings *ts, Object *ob, const bool add_key_index) /** * \warning This can invalidate the #DerivedMesh cache of other objects (for linked duplicates). - * Most callers should run #DAG_id_tag_update on \a ob->data, see: T46738, T46913 + * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 */ void EDBM_mesh_load(Object *ob) { @@ -520,7 +521,6 @@ UvVertMap *BM_uv_vert_map_create( /* vars from original func */ UvVertMap *vmap; UvMapVert *buf; - /* MTexPoly *tf; */ /* UNUSED */ MLoopUV *luv; unsigned int a; int totverts, i, totuv, totfaces; @@ -602,7 +602,6 @@ UvVertMap *BM_uv_vert_map_create( newvlist = v; efa = BM_face_at_index(bm, v->f); - /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->tfindex); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -614,7 +613,6 @@ UvVertMap *BM_uv_vert_map_create( while (iterv) { next = iterv->next; efa = BM_face_at_index(bm, iterv->f); - /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex); luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -929,29 +927,27 @@ UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l) /* last_sel, use em->act_face otherwise get the last selected face in the editselections * at the moment, last_sel is mainly useful for making sure the space image dosnt flicker */ -MTexPoly *EDBM_mtexpoly_active_get(BMEditMesh *em, BMFace **r_act_efa, const bool sloppy, const bool selected) +BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool selected) { BMFace *efa = NULL; - if (!EDBM_mtexpoly_check(em)) + if (!EDBM_uv_check(em)) return NULL; efa = BM_mesh_active_face_get(em->bm, sloppy, selected); if (efa) { - if (r_act_efa) *r_act_efa = efa; - return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + return efa; } - if (r_act_efa) *r_act_efa = NULL; return NULL; } /* can we edit UV's for this mesh?*/ -bool EDBM_mtexpoly_check(BMEditMesh *em) +bool EDBM_uv_check(BMEditMesh *em) { /* some of these checks could be a touch overkill */ - return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) && + return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV); } @@ -1281,7 +1277,7 @@ void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_d { Object *ob = em->ob; /* order of calling isn't important */ - DAG_id_tag_update(ob->data, OB_RECALC_DATA); + DEG_id_tag_update(ob->data, OB_RECALC_DATA); WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data); if (do_tessface) { diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index bd7aaec075b..9ede8d92289 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -42,7 +42,6 @@ #include "BLI_math.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -50,6 +49,8 @@ #include "BKE_report.h" #include "BKE_editmesh.h" +#include "DEG_depsgraph.h" + #include "RNA_define.h" #include "WM_api.h" @@ -245,14 +246,14 @@ void ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum) } } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); } void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me) { /* could be ldata or pdata */ - CustomData *pdata = GET_CD_DATA(me, pdata); - const int layernum = CustomData_get_active_layer(pdata, CD_MTEXPOLY); + CustomData *ldata = GET_CD_DATA(me, ldata); + const int layernum = CustomData_get_active_layer(ldata, CD_MLOOPUV); ED_mesh_uv_loop_reset_ex(me, layernum); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); @@ -269,21 +270,10 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set) if (me->edit_btmesh) { em = me->edit_btmesh; - layernum_dst = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY); + layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV); if (layernum_dst >= MAX_MTFACE) return -1; - /* CD_MTEXPOLY */ - BM_data_layer_add_named(em->bm, &em->bm->pdata, CD_MTEXPOLY, name); - /* copy data from active UV */ - if (layernum_dst) { - const int layernum_src = CustomData_get_active_layer(&em->bm->pdata, CD_MTEXPOLY); - BM_data_layer_copy(em->bm, &em->bm->pdata, CD_MTEXPOLY, layernum_src, layernum_dst); - } - if (active_set || layernum_dst == 0) { - CustomData_set_layer_active(&em->bm->pdata, CD_MTEXPOLY, layernum_dst); - } - /* CD_MLOOPUV */ BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_MLOOPUV, name); /* copy data from active UV */ @@ -298,26 +288,22 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set) } } else { - layernum_dst = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); + layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); if (layernum_dst >= MAX_MTFACE) return -1; - if (me->mtpoly) { - CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DUPLICATE, me->mtpoly, me->totpoly, name); + if (me->mloopuv) { CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name); CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name); is_init = true; } else { - CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, name); CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name); CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name); } if (active_set || layernum_dst == 0) { - CustomData_set_layer_active(&me->pdata, CD_MTEXPOLY, layernum_dst); CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst); - CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum_dst); } @@ -329,7 +315,7 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set) ED_mesh_uv_loop_reset_ex(me, layernum_dst); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); return layernum_dst; @@ -343,12 +329,12 @@ void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name) if (me->edit_btmesh) { em = me->edit_btmesh; - layernum_dst = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY); + layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV); if (layernum_dst == 0) ED_mesh_uv_texture_add(me, name, true); } else { - layernum_dst = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); + layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); if (layernum_dst == 0) ED_mesh_uv_texture_add(me, name, true); } @@ -357,23 +343,19 @@ void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name) bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n) { - CustomData *pdata = GET_CD_DATA(me, pdata), *ldata = GET_CD_DATA(me, ldata); - CustomDataLayer *cdlp, *cdlu; + CustomData *ldata = GET_CD_DATA(me, ldata); + CustomDataLayer *cdlu; int index; - index = CustomData_get_layer_index_n(pdata, CD_MTEXPOLY, n); - cdlp = (index == -1) ? NULL : &pdata->layers[index]; - index = CustomData_get_layer_index_n(ldata, CD_MLOOPUV, n); cdlu = (index == -1) ? NULL : &ldata->layers[index]; - if (!cdlp || !cdlu) + if (!cdlu) return false; - delete_customdata_layer(me, cdlp); delete_customdata_layer(me, cdlu); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); return true; @@ -381,14 +363,8 @@ bool ED_mesh_uv_texture_remove_index(Mesh *me, const int n) bool ED_mesh_uv_texture_remove_active(Mesh *me) { /* texpoly/uv are assumed to be in sync */ - CustomData *pdata = GET_CD_DATA(me, pdata); - const int n = CustomData_get_active_layer(pdata, CD_MTEXPOLY); - - /* double check active layers align! */ -#ifdef DEBUG CustomData *ldata = GET_CD_DATA(me, ldata); - BLI_assert(CustomData_get_active_layer(ldata, CD_MLOOPUV) == n); -#endif + const int n = CustomData_get_active_layer(ldata, CD_MLOOPUV); if (n != -1) { return ED_mesh_uv_texture_remove_index(me, n); @@ -400,8 +376,8 @@ bool ED_mesh_uv_texture_remove_active(Mesh *me) bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name) { /* texpoly/uv are assumed to be in sync */ - CustomData *pdata = GET_CD_DATA(me, pdata); - const int n = CustomData_get_named_layer(pdata, CD_MTEXPOLY, name); + CustomData *ldata = GET_CD_DATA(me, ldata); + const int n = CustomData_get_named_layer(ldata, CD_MLOOPUV, name); if (n != -1) { return ED_mesh_uv_texture_remove_index(me, n); } @@ -458,7 +434,7 @@ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set) BKE_mesh_update_customdata_pointers(me, true); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); return layernum; @@ -473,7 +449,7 @@ bool ED_mesh_color_ensure(struct Mesh *me, const char *name) BKE_mesh_update_customdata_pointers(me, true); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); return (me->mloopcol != NULL); } @@ -491,7 +467,7 @@ bool ED_mesh_color_remove_index(Mesh *me, const int n) return false; delete_customdata_layer(me, cdl); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_main_add_notifier(NC_GEOM | ND_DATA, me); return true; @@ -565,7 +541,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - Base *base; + BaseLegacy *base; Image *ima = NULL; Mesh *me; Object *obedit; @@ -612,7 +588,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e /* load_editMesh free's pointers used by CustomData layers which might be used by DerivedMesh too, * so signal to re-create DerivedMesh here (sergey) */ - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); } /* dummie drop support; ensure view shows a result :) */ @@ -751,7 +727,7 @@ static int mesh_customdata_clear_exec__internal(bContext *C, CustomData_free_layers(data, type, tot); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -847,7 +823,7 @@ static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mesh_ensure_skin_customdata(me); - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -909,7 +885,7 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator CustomData_add_layer(data, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, me->totloop); } - DAG_id_tag_update(&me->id, 0); + DEG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return OPERATOR_FINISHED; @@ -986,7 +962,7 @@ void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges, int calc_tessface) BKE_mesh_calc_normals(mesh); - DAG_id_tag_update(&mesh->id, 0); + DEG_id_tag_update(&mesh->id, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh); } @@ -1306,7 +1282,6 @@ void ED_mesh_calc_tessface(Mesh *mesh, bool free_mpoly) mesh->mloopcol = NULL; mesh->mloopuv = NULL; mesh->mpoly = NULL; - mesh->mtpoly = NULL; } } diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 300b21a052d..99342222d52 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -109,6 +109,11 @@ void MESH_OT_dupli_extrude_cursor(struct wmOperatorType *ot); void MESH_OT_spin(struct wmOperatorType *ot); void MESH_OT_screw(struct wmOperatorType *ot); +/* *** editmesh_polybuild.c *** */ +void MESH_OT_polybuild_face_at_cursor(struct wmOperatorType *ot); +void MESH_OT_polybuild_split_at_cursor(struct wmOperatorType *ot); +void MESH_OT_polybuild_dissolve_at_cursor(struct wmOperatorType *ot); +void MESH_OT_polybuild_hover(struct wmOperatorType *ot); /* *** editmesh_inset.c *** */ void MESH_OT_inset(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index b95921964eb..e5705d2d3e7 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -41,7 +41,6 @@ #include "BLI_linklist.h" #include "BKE_library.h" -#include "BKE_depsgraph.h" #include "BKE_context.h" #include "BKE_mesh.h" #include "BKE_scene.h" @@ -58,6 +57,8 @@ #include "recast-capi.h" +#include "DEG_depsgraph.h" + #include "mesh_intern.h" /* own include */ @@ -72,18 +73,21 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, LinkNode *oblink, *dmlink; DerivedMesh *dm; Scene *scene = CTX_data_scene(C); + EvaluationContext eval_ctx; LinkNode *dms = NULL; int nverts, ntris, *tris; float *verts; + CTX_data_eval_ctx(C, &eval_ctx); + nverts = 0; ntris = 0; /* calculate number of verts and tris */ for (oblink = obs; oblink; oblink = oblink->next) { ob = (Object *) oblink->link; - dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH); + dm = mesh_create_derived_no_virtual(&eval_ctx, scene, ob, NULL, CD_MASK_MESH); DM_ensure_tessface(dm); BLI_linklist_prepend(&dms, dm); @@ -326,7 +330,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert } static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, - Base *base, unsigned int lay) + BaseLegacy *base, unsigned int lay) { float co[3], rot[3]; BMEditMesh *em; @@ -440,7 +444,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, recast_destroyPolyMesh(pmesh); recast_destroyPolyMeshDetail(dmesh); - DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); + DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -461,14 +465,15 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, static int navmesh_create_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); LinkNode *obs = NULL; - Base *navmeshBase = NULL; + BaseLegacy *navmeshBase = NULL; CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { if (base->object->type == OB_MESH) { if (base->object->body_type == OB_BODY_TYPE_NAVMESH) { - if (!navmeshBase || base == scene->basact) { + if (!navmeshBase || base == sl->basact) { navmeshBase = base; } } @@ -551,7 +556,7 @@ static int navmesh_face_copy_exec(bContext *C, wmOperator *op) } } - DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); + DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -632,7 +637,7 @@ static int navmesh_face_add_exec(bContext *C, wmOperator *UNUSED(op)) } } - DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); + DEG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); return OPERATOR_FINISHED; @@ -681,7 +686,7 @@ static int navmesh_reset_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mesh_ensure_navmesh(me); - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, &me->id); return OPERATOR_FINISHED; @@ -709,7 +714,7 @@ static int navmesh_clear_exec(bContext *C, wmOperator *UNUSED(op)) CustomData_free_layers(&me->pdata, CD_RECAST, me->totpoly); - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM | ND_DATA, &me->id); return OPERATOR_FINISHED; diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 697a92f36d1..b9920f9deca 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -147,7 +147,13 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_rip_edge); WM_operatortype_append(MESH_OT_blend_from_shape); WM_operatortype_append(MESH_OT_shape_propagate_to_all); - + + /* editmesh_polybuild */ + WM_operatortype_append(MESH_OT_polybuild_face_at_cursor); + WM_operatortype_append(MESH_OT_polybuild_split_at_cursor); + WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor); + WM_operatortype_append(MESH_OT_polybuild_hover); + WM_operatortype_append(MESH_OT_uv_texture_add); WM_operatortype_append(MESH_OT_uv_texture_remove); WM_operatortype_append(MESH_OT_vertex_color_add); @@ -298,6 +304,23 @@ void ED_operatormacros_mesh(void) otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); RNA_boolean_set(otmacro->ptr, "mirror", false); + + + ot = WM_operatortype_append_macro( + "MESH_OT_polybuild_face_at_cursor_move", "Face At Cursor Move", "", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MESH_OT_polybuild_face_at_cursor"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_enum_set(otmacro->ptr, "proportional", 0); + RNA_boolean_set(otmacro->ptr, "mirror", false); + + ot = WM_operatortype_append_macro( + "MESH_OT_polybuild_split_at_cursor_move", "Split At Cursor Move", "", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MESH_OT_polybuild_split_at_cursor"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_enum_set(otmacro->ptr, "proportional", 0); + RNA_boolean_set(otmacro->ptr, "mirror", false); } /* note mesh keymap also for other space? */ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index c900373a59c..da0da05bb13 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -49,7 +49,6 @@ #include "BLI_kdtree.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" #include "BKE_key.h" @@ -62,6 +61,9 @@ #include "BKE_editmesh.h" #include "BKE_multires.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_mesh.h" #include "ED_object.h" #include "ED_view3d.h" @@ -77,7 +79,7 @@ * return 0 if no join is made (error) and 1 if the join is done */ static void join_mesh_single( - Main *bmain, Scene *scene, + bContext *C, Main *bmain, Scene *scene, Object *ob_dst, Object *ob_src, float imat[4][4], MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp, CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata, @@ -86,6 +88,7 @@ static void join_mesh_single( Material **matar, int *matmap, int totcol, int *vertofs, int *edgeofs, int *loopofs, int *polyofs) { + EvaluationContext eval_ctx; int a, b; Mesh *me = ob_src->data; @@ -94,6 +97,8 @@ static void join_mesh_single( MLoop *mloop = *mloop_pp; MPoly *mpoly = *mpoly_pp; + CTX_data_eval_ctx(C, &eval_ctx); + if (me->totvert) { /* merge customdata flag */ ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag; @@ -214,7 +219,7 @@ static void join_mesh_single( if (ob_src != ob_dst) { MultiresModifierData *mmd; - multiresModifier_prepare_join(scene, ob_src, ob_dst); + multiresModifier_prepare_join(&eval_ctx, scene, ob_src, ob_dst); if ((mmd = get_multires_modifier(scene, ob_src, true))) { ED_object_iter_other(bmain, ob_src, true, @@ -493,7 +498,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) * active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084. */ join_mesh_single( - bmain, scene, + C, bmain, scene, ob, ob, imat, &mvert, &medge, &mloop, &mpoly, &vdata, &edata, &ldata, &pdata, @@ -510,7 +515,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* only join if this is a mesh */ if (base->object->type == OB_MESH) { join_mesh_single( - bmain, scene, + C, bmain, scene, ob, base->object, imat, &mvert, &medge, &mloop, &mpoly, &vdata, &edata, &ldata, &pdata, @@ -521,7 +526,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* free base, now that data is merged */ if (base->object != ob) { - ED_base_object_free_and_unlink(bmain, scene, base); + ED_base_object_free_and_unlink(bmain, scene, base->object); } } } @@ -594,9 +599,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* Due to dependnecy cycle some other object might access old derived data. */ BKE_object_free_derived_caches(ob); - DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ + DEG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); @@ -612,6 +617,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; Mesh *me = (Mesh *)ob->data; Mesh *selme = NULL; DerivedMesh *dm = NULL; @@ -619,6 +625,8 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) KeyBlock *kb; bool ok = false, nonequal_verts = false; + CTX_data_eval_ctx(C, &eval_ctx); + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { if (base->object == ob) continue; @@ -660,7 +668,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) selme = (Mesh *)base->object->data; if (selme->totvert == me->totvert) { - dm = mesh_get_derived_deform(scene, base->object, CD_MASK_BAREMESH); + dm = mesh_get_derived_deform(&eval_ctx, scene, base->object, CD_MASK_BAREMESH); if (!dm) continue; @@ -1088,6 +1096,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm) */ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size) { + EvaluationContext eval_ctx; ViewContext vc; Mesh *me = ob->data; @@ -1096,6 +1105,7 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int if (!me || me->totpoly == 0) return false; + CTX_data_eval_ctx(C, &eval_ctx); view3d_set_viewcontext(C, &vc); if (size) { @@ -1103,11 +1113,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int * on an edge in the backbuf, we can still select a face */ float dummy_dist; - *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist); + *index = ED_view3d_backbuf_sample_rect(&eval_ctx, &vc, mval, size, 1, me->totpoly + 1, &dummy_dist); } else { /* sample only on the exact position */ - *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); + *index = ED_view3d_backbuf_sample(&eval_ctx, &vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totpoly) @@ -1146,9 +1156,12 @@ static void ed_mesh_pick_face_vert__mpoly_find( */ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size) { + EvaluationContext eval_ctx; unsigned int poly_index; Mesh *me = ob->data; + CTX_data_eval_ctx(C, &eval_ctx); + BLI_assert(me && GS(me->id.name) == ID_ME); if (ED_mesh_pick_face(C, ob, mval, &poly_index, size)) { @@ -1156,7 +1169,7 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned struct ARegion *ar = CTX_wm_region(C); /* derived mesh to find deformed locations */ - DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); + DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); int v_idx_best = ORIGINDEX_NONE; @@ -1253,9 +1266,12 @@ static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co } bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf) { + EvaluationContext eval_ctx; ViewContext vc; Mesh *me = ob->data; + CTX_data_eval_ctx(C, &eval_ctx); + BLI_assert(me && GS(me->id.name) == ID_ME); if (!me || me->totvert == 0) @@ -1269,11 +1285,11 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int * on an face in the backbuf, we can still select a vert */ float dummy_dist; - *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist); + *index = ED_view3d_backbuf_sample_rect(&eval_ctx, &vc, mval, size, 1, me->totvert + 1, &dummy_dist); } else { /* sample only on the exact position */ - *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); + *index = ED_view3d_backbuf_sample(&eval_ctx, &vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totvert) @@ -1283,7 +1299,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int } else { /* derived mesh to find deformed locations */ - DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_final(&eval_ctx, vc.scene, ob, CD_MASK_BAREMESH); ARegion *ar = vc.ar; RegionView3D *rv3d = ar->regiondata; |