diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-09-09 09:11:02 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-09-10 07:35:04 +0300 |
commit | 20634fd433b07bbd90358a625792292e9581a0f6 (patch) | |
tree | b6be45ddf341ce7d2dc8c85a67480e6815d4a6e6 /source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c | |
parent | 2b5d4d426a9b8483539d14b6e9ab90da262c2ecb (diff) |
Tool System: use preselect highlight w/ poly-build
- Poly build now uses a new gizmo for pre-selection
which has the same behavior as loop-cut.
This replaces hack where mouse-move set the active element
which was no longer working properly because of missing
depsgraph updates.
- Multi-object support for poly-build.
- Support for deformed cage.
- Fix error where changing active object wasn't properly
refreshing the preselect gizmo (for loopcut too).
Currently holding Alt to select non-boundary element's isn't working.
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c | 220 |
1 files changed, 217 insertions, 3 deletions
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c index fffca6c0887..33de6621db3 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -55,6 +55,207 @@ #include "ED_gizmo_library.h" /* -------------------------------------------------------------------- */ +/** \name Mesh Element (Vert/Edge/Face) Pre-Select Gizmo API + * + * \{ */ + + +typedef struct MeshElemGizmo3D { + wmGizmo gizmo; + Object **objects; + uint objects_len; + int object_index; + int vert_index; + int edge_index; + int face_index; + struct EditMesh_PreSelElem *psel; +} MeshElemGizmo3D; + +static void gizmo_preselect_elem_draw(const bContext *UNUSED(C), wmGizmo *gz) +{ + MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + if (gz_ele->object_index != -1) { + Object *ob = gz_ele->objects[gz_ele->object_index]; + EDBM_preselect_elem_draw(gz_ele->psel, ob->obmat); + } +} + +static int gizmo_preselect_elem_test_select( + bContext *C, wmGizmo *gz, const int mval[2]) +{ + MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + struct { + Object *ob; + BMElem *ele; + float dist; + int ob_index; + } best = { + .dist = ED_view3d_select_dist_px(), + }; + + struct { + int object_index; + int vert_index; + int edge_index; + int face_index; + } prev = { + .object_index = gz_ele->object_index, + .vert_index = gz_ele->vert_index, + .edge_index = gz_ele->edge_index, + .face_index = gz_ele->face_index, + }; + + { + ViewLayer *view_layer = CTX_data_view_layer(C); + if (((gz_ele->objects)) == NULL || + (gz_ele->objects[0] != OBEDIT_FROM_VIEW_LAYER(view_layer))) + { + gz_ele->objects = BKE_view_layer_array_from_objects_in_edit_mode( + view_layer, &gz_ele->objects_len); + } + } + + ViewContext vc; + em_setup_viewcontext(C, &vc); + copy_v2_v2_int(vc.mval, mval); + + { + /* TODO: support faces. */ + Base *base = NULL; + BMVert *eve_test; + BMEdge *eed_test; + + if (EDBM_unified_findnearest_from_raycast(&vc, true, &base, &eve_test, &eed_test, NULL)) { + best.ob = base->object; + if (eve_test) { + best.ele = (BMElem *)eve_test; + } + else if (eed_test) { + best.ele = (BMElem *)eed_test; + } + else { + BLI_assert(0); + } + best.ob_index = -1; + /* weak, we could ensure the arrays are aligned, + * or allow EDBM_unified_findnearest_from_raycast to take an array arg. */ + for (int ob_index = 0; ob_index < gz_ele->objects_len; ob_index++) { + if (best.ob == gz_ele->objects[ob_index]) { + best.ob_index = ob_index; + break; + } + } + /* Check above should never fail, if it does it's an internal error. */ + BLI_assert(best.ob_index != -1); + } + } + + BMesh *bm = NULL; + + gz_ele->object_index = -1; + gz_ele->vert_index = -1; + gz_ele->edge_index = -1; + gz_ele->face_index = -1; + + if (best.ele) { + gz_ele->object_index = best.ob_index; + bm = BKE_editmesh_from_object(gz_ele->objects[gz_ele->object_index])->bm; + BM_mesh_elem_index_ensure(bm, best.ele->head.htype); + + if (best.ele->head.htype == BM_VERT) { + gz_ele->vert_index = BM_elem_index_get(best.ele); + } + else if (best.ele->head.htype == BM_EDGE) { + gz_ele->edge_index = BM_elem_index_get(best.ele); + } + else if (best.ele->head.htype == BM_FACE) { + gz_ele->face_index = BM_elem_index_get(best.ele); + } + } + + if ((prev.object_index == gz_ele->object_index) && + (prev.vert_index == gz_ele->vert_index) && + (prev.edge_index == gz_ele->edge_index) && + (prev.face_index == gz_ele->face_index)) + { + /* pass (only recalculate on change) */ + } + else { + if (best.ele) { + const float (*coords)[3] = NULL; + { + Object *ob = gz_ele->objects[gz_ele->object_index]; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); + if (me_eval->runtime.edit_data) { + coords = me_eval->runtime.edit_data->vertexCos; + } + } + EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords); + } + else { + EDBM_preselect_elem_clear(gz_ele->psel); + } + + RNA_int_set(gz->ptr, "object_index", gz_ele->object_index); + RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index); + RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index); + RNA_int_set(gz->ptr, "face_index", gz_ele->face_index); + + ARegion *ar = CTX_wm_region(C); + ED_region_tag_redraw(ar); + } + + // return best.eed ? 0 : -1; + return -1; +} + +static void gizmo_preselect_elem_setup(wmGizmo *gz) +{ + MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + if (gz_ele->psel == NULL) { + gz_ele->psel = EDBM_preselect_elem_create(); + } + gz_ele->object_index = -1; +} + +static void gizmo_preselect_elem_free(wmGizmo *gz) +{ + MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + EDBM_preselect_elem_destroy(gz_ele->psel); + gz_ele->psel = NULL; + MEM_SAFE_FREE(gz_ele->objects); +} + +static int gizmo_preselect_elem_invoke( + bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event)) +{ + return OPERATOR_PASS_THROUGH; +} + +static void GIZMO_GT_preselect_elem_3d(wmGizmoType *gzt) +{ + /* identifiers */ + gzt->idname = "GIZMO_GT_preselect_elem_3d"; + + /* api callbacks */ + gzt->invoke = gizmo_preselect_elem_invoke; + gzt->draw = gizmo_preselect_elem_draw; + gzt->test_select = gizmo_preselect_elem_test_select; + gzt->setup = gizmo_preselect_elem_setup; + gzt->free = gizmo_preselect_elem_free; + + gzt->struct_size = sizeof(MeshElemGizmo3D); + + RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "vert_index", -1, -1, INT_MAX, "Vert Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "face_index", -1, -1, INT_MAX, "Face Index", "", -1, INT_MAX); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Mesh Edge-Ring Pre-Select Gizmo API * * \{ */ @@ -98,10 +299,14 @@ static int gizmo_preselect_edgering_test_select( .edge_index = gz_ring->edge_index, }; - if (gz_ring->objects == NULL) { + { ViewLayer *view_layer = CTX_data_view_layer(C); - gz_ring->objects = BKE_view_layer_array_from_objects_in_edit_mode( - view_layer, &gz_ring->objects_len); + if (((gz_ring->objects)) == NULL || + (gz_ring->objects[0] != OBEDIT_FROM_VIEW_LAYER(view_layer))) + { + gz_ring->objects = BKE_view_layer_array_from_objects_in_edit_mode( + view_layer, &gz_ring->objects_len); + } } ViewContext vc; @@ -207,8 +412,17 @@ static void GIZMO_GT_preselect_edgering_3d(wmGizmoType *gzt) RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX); } +/** \} */ + + +/* -------------------------------------------------------------------- */ +/** \name Gizmo API + * + * \{ */ + void ED_gizmotypes_preselect_3d(void) { + WM_gizmotype_append(GIZMO_GT_preselect_elem_3d); WM_gizmotype_append(GIZMO_GT_preselect_edgering_3d); } |