Tool System: loopcut preview & activate on click
authorCampbell Barton <ideasman42@gmail.com>
Tue, 21 Aug 2018 09:02:28 +0000 (19:02 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 21 Aug 2018 09:05:07 +0000 (19:05 +1000)
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.

release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
source/blender/editors/include/ED_gizmo_library.h
source/blender/editors/mesh/editmesh_loopcut.c
source/blender/editors/space_api/spacetypes.c
source/blender/editors/space_view3d/CMakeLists.txt
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_gizmo_preselect.c [new file with mode: 0644]
source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c [new file with mode: 0644]
source/blender/editors/space_view3d/view3d_intern.h

index 54499bb4ac3fcef1bc9101841607aeb98bff5375..87d30dc3c69d19810f171c6777ad1019028b533a 100644 (file)
@@ -679,7 +679,7 @@ class _defs_edit_mesh:
         return dict(
             text="Loop Cut",
             icon="ops.mesh.loopcut_slide",
-            widget=None,
+            widget="VIEW3D_GGT_mesh_preselect_edgering",
             keymap=(
                 ("mesh.loopcut_slide", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
             ),
index 41488baa964f8704de364927ffc03111682dd654..adc6f859111538e1c56f764fc801fa3e8edb23d7 100644 (file)
@@ -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);
 
index 727b595bbe0f45ac138f0b6b3d25fc45f827bdd2..4fc57224580a762477bcb2df8ea290f1a1f24966 100644 (file)
@@ -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);
 }
 
index 84de55a172d0865aba798e7b1bde0913c500ec13..5492cf13564f0b9ed1d755a79856f168016675be 100644 (file)
@@ -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();
index b85525dd2ee2ee1322ca02699ae6cd2d33f6b2dd..4bcec142aa9305d4e84428c4b5b408d55e5ef596 100644 (file)
@@ -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
index 1d254d608b28fe899748c7842ce367adc51b4302..434cb108ef44c9447e243c859bb4625d08c3db87 100644 (file)
@@ -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 (file)
index 0000000..aebad32
--- /dev/null
@@ -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 (file)
index 0000000..2934c55
--- /dev/null
@@ -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);
+}
+
+/** \} */
index 855ee7bb9fc82080ed58b7018caac059f547949b..e4ef442d49a5ed2ba014f2b5bea04d4f9f40e803 100644 (file)
@@ -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);