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.
This commit is contained in:
@@ -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')),
|
||||
),
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
89
source/blender/editors/space_view3d/view3d_gizmo_preselect.c
Normal file
89
source/blender/editors/space_view3d/view3d_gizmo_preselect.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user