[Bf-blender-cvs] [c10359c] GPencil_EditStrokes: GPencil: Added operator to allow directly clicking on strokes to select them and their points
Joshua Leung
noreply at git.blender.org
Sat Oct 11 00:36:39 CEST 2014
Commit: c10359cb81e5d2bc4c7647dc1987ae73f45dcd7b
Author: Joshua Leung
Date: Sat Oct 11 11:29:23 2014 +1300
Branches: GPencil_EditStrokes
https://developer.blender.org/rBc10359cb81e5d2bc4c7647dc1987ae73f45dcd7b
GPencil: Added operator to allow directly clicking on strokes to select them and their points
* D RMB = Select the stroke point under the cursor
* D Shift RMB = Select the stroke point udner the cursor, while retaining existing selection
* D W = Select whole stroke
As a result of these changes, the eraser has had to be moved to another binding,
i.e. D X. This doesn't really work that great since it starts working immediately.
===================================================================
M source/blender/editors/gpencil/gpencil_intern.h
M source/blender/editors/gpencil/gpencil_ops.c
M source/blender/editors/gpencil/gpencil_select.c
===================================================================
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 2f91bff..e69afa9 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -115,6 +115,7 @@ typedef enum eGPencil_PaintModes {
/* stroke editing ----- */
+void GPENCIL_OT_select(struct wmOperatorType *ot);
void GPENCIL_OT_select_all(struct wmOperatorType *ot);
void GPENCIL_OT_select_circle(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 46f9810..70d1f56 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -68,7 +68,7 @@ void ED_keymap_gpencil(wmKeyConfig *keyconf)
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY);
/* erase */
- kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, 0, DKEY);
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", XKEY, KM_PRESS, 0, DKEY);
RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER);
/* Selection ------------------------------------- */
@@ -83,6 +83,17 @@ void ED_keymap_gpencil(wmKeyConfig *keyconf)
/* circle select */
WM_keymap_add_item(keymap, "GPENCIL_OT_select_circle", CKEY, KM_PRESS, 0, DKEY);
+ /* normal select */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_select", RIGHTMOUSE, KM_PRESS, 0, DKEY);
+
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", RIGHTMOUSE, KM_PRESS, KM_SHIFT, DKEY);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+
+ /* whole stroke select */
+ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", WKEY, KM_PRESS, 0, DKEY);
+ RNA_boolean_set(kmi->ptr, "entire_strokes", true);
+
+
/* Editing ----------------------------------------- */
WM_keymap_add_item(keymap, "GPENCIL_OT_strokes_duplicate", EKEY, KM_PRESS, 0, DKEY);
@@ -109,6 +120,7 @@ void ED_operatortypes_gpencil(void)
/* Editing (Strokes) ------------ */
+ WM_operatortype_append(GPENCIL_OT_select);
WM_operatortype_append(GPENCIL_OT_select_all);
WM_operatortype_append(GPENCIL_OT_select_circle);
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 6875014..6088c63 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -362,5 +362,216 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot)
}
/* ********************************************** */
+/* Mouse Click to Select */
+
+static int gpencil_select_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+
+ Scene *scene = CTX_data_scene(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
+ const float radius = 0.35f * U.widget_unit;
+ const int radius_squared = (int)(radius * radius);
+
+ rctf *subrect = NULL; /* for using the camera rect within the 3d view */
+ rctf subrect_data = {0.0f};
+
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool whole = RNA_boolean_get(op->ptr, "entire_strokes");
+
+ int location[2] = {0};
+ int mx, my;
+
+ bGPDstroke *hit_stroke = NULL;
+ bGPDspoint *hit_point = NULL;
+
+ /* sanity checks */
+ if (gpd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+ return OPERATOR_CANCELLED;
+ }
+ if (sa == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active area");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* for 3D View, init depth buffer stuff used for 3D projections... */
+ if (sa->spacetype == SPACE_VIEW3D) {
+ wmWindow *win = CTX_wm_window(C);
+ View3D *v3d = (View3D *)CTX_wm_space_data(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* init 3d depth buffers */
+ view3d_operator_needs_opengl(C);
+ view3d_region_operator_needs_opengl(win, ar);
+ ED_view3d_autodist_init(scene, ar, v3d, 0);
+
+ /* for camera view set the subrect */
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &subrect_data, true); /* no shift */
+ subrect = &subrect_data;
+ }
+ }
+
+ /* get mouse location */
+ RNA_int_get_array(op->ptr, "location", location);
+
+ mx = location[0];
+ my = location[1];
+
+ /* First Pass: Find stroke point which gets hit */
+ /* XXX: maybe we should go from the top of the stack down instead... */
+ GP_VISIBLE_STROKES_ITER_BEGIN(gpd, gps)
+ {
+ bGPDspoint *pt;
+ int i;
+ int hit_index = -1;
+
+ /* firstly, check for hit-point */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int x0, y0;
+
+ gp_point_to_xy(ar, v2d, subrect, gps, pt, &x0, &y0);
+
+ /* do boundbox check first */
+ if (!ELEM(V2D_IS_CLIPPED, x0, x0)) {
+ /* only check if point is inside */
+ if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius_squared) {
+ hit_stroke = gps;
+ hit_point = pt;
+ break;
+ }
+ }
+ }
+
+ /* skip to next stroke if nothing found */
+ if (hit_index == -1)
+ continue;
+ }
+ GP_STROKES_ITER_END;
+
+ /* Abort if nothing hit... */
+ if (ELEM(NULL, hit_stroke, hit_point)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* adjust selection behaviour - for toggle option */
+ if (toggle) {
+ deselect = (hit_point->flag & GP_SPOINT_SELECT) != 0;
+ }
+
+ /* If not extending selection, deselect everything else */
+ if (extend == false) {
+ GP_VISIBLE_STROKES_ITER_BEGIN(gpd, gps)
+ {
+ /* deselect stroke and its points if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* deselect points */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* deselect stroke itself too */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ GP_STROKES_ITER_END;
+ }
+
+ /* Perform selection operations... */
+ if (whole) {
+ bGPDspoint *pt;
+ int i;
+
+ /* entire stroke's points */
+ for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
+ if (deselect == false)
+ pt->flag |= GP_SPOINT_SELECT;
+ else
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* stroke too... */
+ if (deselect == false)
+ hit_stroke->flag |= GP_STROKE_SELECT;
+ else
+ hit_stroke->flag &= ~GP_STROKE_SELECT;
+ }
+ else {
+ /* just the point (and the stroke) */
+ if (deselect == false) {
+ /* we're adding selection, so selection must be true */
+ hit_point->flag |= GP_SPOINT_SELECT;
+ hit_stroke->flag |= GP_STROKE_SELECT;
+ }
+ else {
+ bGPDspoint *pt;
+ int i;
+
+ /* deselect point */
+ hit_point->flag &= ~GP_SPOINT_SELECT;
+
+ /* ensure that stroke is selected correctly */
+ hit_stroke->flag &= ~GP_STROKE_SELECT;
+
+ for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) {
+ if (pt->flag & GP_SPOINT_SELECT) {
+ hit_stroke->flag |= GP_STROKE_SELECT;
+ break;
+ }
+ }
+ }
+ }
+
+ /* updates */
+ if (hit_point != NULL) {
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ RNA_int_set_array(op->ptr, "location", event->mval);
+ return gpencil_select_exec(C, op);
+}
+
+void GPENCIL_OT_select(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select";
+ ot->description = "Select Grease Pencil strokes and/or stroke points";
+ ot->idname = "GPENCIL_OT_select";
+
+ /* callbacks */
+ ot->invoke = gpencil_select_invoke;
+ ot->exec = gpencil_select_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flag */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_mouse_select(ot);
+
+ RNA_def_boolean(ot->srna, "entire_strokes", false, "Entire Strokes", "Select entire strokes instead of just the nearest stroke vertex");
+
+ prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+}
+
+/* ********************************************** */
\ No newline at end of file
More information about the Bf-blender-cvs
mailing list