From 79ecfc99fd75f897a6140639474a7b0e5910a9ff Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 21 Aug 2018 19:02:28 +1000 Subject: Tool System: loopcut preview & activate on click The loop cut tool now works as expected for the tool-system, where hovering previews the loop and clicking activates. This uses a new gizmo type to pre-select the edge. --- source/blender/editors/include/ED_gizmo_library.h | 1 + source/blender/editors/mesh/editmesh_loopcut.c | 19 ++ source/blender/editors/space_api/spacetypes.c | 1 + source/blender/editors/space_view3d/CMakeLists.txt | 2 + source/blender/editors/space_view3d/space_view3d.c | 1 + .../editors/space_view3d/view3d_gizmo_preselect.c | 89 +++++++++ .../space_view3d/view3d_gizmo_preselect_type.c | 203 +++++++++++++++++++++ .../blender/editors/space_view3d/view3d_intern.h | 1 + 8 files changed, 317 insertions(+) create mode 100644 source/blender/editors/space_view3d/view3d_gizmo_preselect.c create mode 100644 source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c (limited to 'source/blender') diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h index 41488baa964..adc6f859111 100644 --- a/source/blender/editors/include/ED_gizmo_library.h +++ b/source/blender/editors/include/ED_gizmo_library.h @@ -39,6 +39,7 @@ void ED_gizmotypes_cage_3d(void); void ED_gizmotypes_dial_3d(void); void ED_gizmotypes_grab_3d(void); void ED_gizmotypes_facemap_3d(void); +void ED_gizmotypes_preselect_3d(void); void ED_gizmotypes_primitive_3d(void); void ED_gizmotypes_blank_3d(void); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 727b595bbe0..4fc57224580 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -436,6 +436,25 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) static int ringcut_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + /* When accessed as a tool, get the active edge from the preselection gizmo. */ + { + ARegion *ar = CTX_wm_region(C); + wmGizmoMap *gzmap = ar->gizmo_map; + wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_mesh_preselect_edgering") : NULL; + if (gzgroup != NULL) { + wmGizmo *gz = gzgroup->gizmos.first; + const int object_index = RNA_int_get(gz->ptr, "object_index"); + const int edge_index = RNA_int_get(gz->ptr, "edge_index"); + + if (object_index != -1 && edge_index != -1) { + RNA_int_set(op->ptr, "object_index", object_index); + RNA_int_set(op->ptr, "edge_index", edge_index); + return loopcut_init(C, op, NULL); + } + return OPERATOR_CANCELLED; + } + } + return loopcut_init(C, op, event); } diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 84de55a172d..5492cf13564 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -135,6 +135,7 @@ void ED_spacetypes_init(void) ED_gizmotypes_grab_3d(); ED_gizmotypes_arrow_2d(); ED_gizmotypes_arrow_3d(); + ED_gizmotypes_preselect_3d(); ED_gizmotypes_primitive_3d(); ED_gizmotypes_blank_3d(); ED_gizmotypes_cage_2d(); diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index b85525dd2ee..4bcec142aa9 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -63,6 +63,8 @@ set(SRC view3d_gizmo_navigate.c view3d_gizmo_navigate_type.c view3d_gizmo_ruler.c + view3d_gizmo_preselect.c + view3d_gizmo_preselect_type.c view3d_ops.c view3d_project.c view3d_ruler.c diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 1d254d608b2..434cb108ef4 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -705,6 +705,7 @@ static void view3d_widgets(void) WM_gizmogrouptype_append(TRANSFORM_GGT_gizmo); WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage); + WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_edgering); WM_gizmogrouptype_append(VIEW3D_GGT_ruler); WM_gizmotype_append(VIEW3D_GT_ruler_item); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c new file mode 100644 index 00000000000..aebad326a57 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c @@ -0,0 +1,89 @@ +/* + * ***** 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/space_view3d/view3d_gizmo_preselect.c + * \ingroup spview3d + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" + +#include "ED_screen.h" + +#include "UI_resources.h" + +#include "WM_api.h" +#include "WM_types.h" +#include "WM_toolsystem.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ +/** \name Mesh Pre-Select Edge Ring Gizmo + * + * \{ */ + +struct GizmoGroupPreSelEdgeRing { + wmGizmo *gizmo; +}; + +static bool WIDGETGROUP_mesh_preselect_edgering_poll(const bContext *C, wmGizmoGroupType *gzgt) +{ + bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C); + if ((tref_rt == NULL) || + !STREQ(gzgt->idname, tref_rt->gizmo_group)) + { + WM_gizmo_group_type_unlink_delayed_ptr(gzgt); + return false; + } + return true; +} + +static void WIDGETGROUP_mesh_preselect_edgering_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +{ + const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_preselect_edgering_3d", true); + struct GizmoGroupPreSelEdgeRing *man = MEM_callocN(sizeof(struct GizmoGroupPreSelEdgeRing), __func__); + gzgroup->customdata = man; + + wmGizmo *gz = man->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL); + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); +} + +void VIEW3D_GGT_mesh_preselect_edgering(wmGizmoGroupType *gzgt) +{ + gzgt->name = "Mesh Preselect Edge Ring"; + gzgt->idname = "VIEW3D_GGT_mesh_preselect_edgering"; + + gzgt->flag = WM_GIZMOGROUPTYPE_3D; + + gzgt->gzmap_params.spaceid = SPACE_VIEW3D; + gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; + + gzgt->poll = WIDGETGROUP_mesh_preselect_edgering_poll; + gzgt->setup = WIDGETGROUP_mesh_preselect_edgering_setup; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c new file mode 100644 index 00000000000..2934c55df6e --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -0,0 +1,203 @@ +/* + * ***** 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 view3d_gizmo_preselect_type.c + * \ingroup wm + * + * \name Preselection Gizmo + * + * Use for tools to hover over data before activation. + * + * \note This is a slight mis-use of gizmo's, since clicking performs no action. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_layer.h" +#include "BKE_editmesh.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "bmesh.h" + +#include "ED_screen.h" +#include "ED_mesh.h" +#include "ED_view3d.h" +#include "ED_gizmo_library.h" + +/* -------------------------------------------------------------------- */ +/** \name Mesh Edge-Ring Pre-Select Gizmo API + * + * \{ */ + +typedef struct MeshEdgeRingGizmo3D { + wmGizmo gizmo; + Object **objects; + uint objects_len; + int object_index; + int edge_index; + struct EditMesh_PreSelEdgeRing *psel; +} MeshEdgeRingGizmo3D; + +static void gizmo_preselect_edgering_draw(const bContext *UNUSED(C), wmGizmo *gz) +{ + MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; + if (gz_ring->object_index != -1) { + Object *ob = gz_ring->objects[gz_ring->object_index]; + EDBM_preselect_edgering_draw(gz_ring->psel, ob->obmat); + } +} + +static int gizmo_preselect_edgering_test_select( + bContext *C, wmGizmo *gz, const int mval[2]) +{ + MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; + struct { + Object *ob; + BMEdge *eed; + float dist; + int ob_index; + } best = { + .dist = ED_view3d_select_dist_px(), + }; + + struct { + int object_index; + int edge_index; + } prev = { + .object_index = gz_ring->object_index, + .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); + } + + ViewContext vc; + em_setup_viewcontext(C, &vc); + copy_v2_v2_int(vc.mval, mval); + + for (uint ob_index = 0; ob_index < gz_ring->objects_len; ob_index++) { + Object *ob_iter = gz_ring->objects[ob_index]; + ED_view3d_viewcontext_init_object(&vc, ob_iter); + BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL); + if (eed_test) { + best.ob = ob_iter; + best.eed = eed_test; + best.ob_index = ob_index; + } + } + + BMesh *bm = NULL; + if (best.eed) { + gz_ring->object_index = best.ob_index; + bm = BKE_editmesh_from_object(gz_ring->objects[gz_ring->object_index])->bm; + BM_mesh_elem_index_ensure(bm, BM_EDGE); + gz_ring->edge_index = BM_elem_index_get(best.eed); + } + else { + gz_ring->object_index = -1; + gz_ring->edge_index = -1; + } + + + if ((prev.object_index == gz_ring->object_index) && + (prev.edge_index == gz_ring->edge_index)) + { + /* pass (only recalculate on change) */ + } + else { + if (best.eed) { + EDBM_preselect_edgering_update_from_edge( + gz_ring->psel, + bm, best.eed, 1); + } + else { + EDBM_preselect_edgering_clear(gz_ring->psel); + } + + RNA_int_set(gz->ptr, "object_index", gz_ring->object_index); + RNA_int_set(gz->ptr, "edge_index", gz_ring->edge_index); + + ARegion *ar = CTX_wm_region(C); + ED_region_tag_redraw(ar); + } + + // return best.eed ? 0 : -1; + return -1; +} + +static void gizmo_preselect_edgering_setup(wmGizmo *gz) +{ + MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; + if (gz_ring->psel == NULL) { + gz_ring->psel = EDBM_preselect_edgering_create(); + } + gz_ring->object_index = -1; +} + +static void gizmo_preselect_edgering_free(wmGizmo *gz) +{ + MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; + EDBM_preselect_edgering_destroy(gz_ring->psel); + gz_ring->psel = NULL; + MEM_SAFE_FREE(gz_ring->objects); +} + +static int gizmo_preselect_edgering_invoke( + bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event)) +{ + return OPERATOR_PASS_THROUGH; +} + + +static void GIZMO_GT_preselect_edgering_3d(wmGizmoType *gzt) +{ + /* identifiers */ + gzt->idname = "GIZMO_GT_preselect_edgering_3d"; + + /* api callbacks */ + gzt->invoke = gizmo_preselect_edgering_invoke; + gzt->draw = gizmo_preselect_edgering_draw; + gzt->test_select = gizmo_preselect_edgering_test_select; + gzt->setup = gizmo_preselect_edgering_setup; + gzt->free = gizmo_preselect_edgering_free; + + gzt->struct_size = sizeof(MeshEdgeRingGizmo3D); + + RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX); +} + +void ED_gizmotypes_preselect_3d(void) +{ + WM_gizmotype_append(GIZMO_GT_preselect_edgering_3d); +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 855ee7bb9fc..e4ef442d49a 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -263,6 +263,7 @@ void VIEW3D_GGT_force_field(struct wmGizmoGroupType *gzgt); void VIEW3D_GGT_empty_image(struct wmGizmoGroupType *gzgt); void VIEW3D_GGT_armature_spline(struct wmGizmoGroupType *gzgt); void VIEW3D_GGT_navigate(struct wmGizmoGroupType *gzgt); +void VIEW3D_GGT_mesh_preselect_edgering(struct wmGizmoGroupType *gzgt); void VIEW3D_GGT_ruler(struct wmGizmoGroupType *gzgt); void VIEW3D_GT_ruler_item(struct wmGizmoType *gzt); -- cgit v1.2.3