[Bf-blender-cvs] [70421bbe34f] soc-2020-greasepencil-curve: GPencil: Add point selection for curve handles
Falk David
noreply at git.blender.org
Wed Jun 17 23:02:19 CEST 2020
Commit: 70421bbe34f286bdac4b0dd383dbcdcddaaa20f6
Author: Falk David
Date: Wed Jun 17 23:01:37 2020 +0200
Branches: soc-2020-greasepencil-curve
https://developer.blender.org/rB70421bbe34f286bdac4b0dd383dbcdcddaaa20f6
GPencil: Add point selection for curve handles
===================================================================
M source/blender/editors/gpencil/gpencil_select.c
===================================================================
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index b104cf5f0e4..765c2969ac4 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -59,6 +59,7 @@
#include "ED_gpencil.h"
#include "ED_select_utils.h"
+#include "ED_view3d.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -131,6 +132,31 @@ static bool gpencil_select_poll(bContext *C)
return false;
}
+static bool error_threshold_display_poll(bContext *C)
+{
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if (gps->editcurve == NULL) {
+ return true;
+ }
+ }
+ CTX_DATA_END;
+ return false;
+}
+
+static void gpencil_select_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ PointerRNA ptr;
+
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = ob->data;
+
+ if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd) && error_threshold_display_poll(C)) {
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiItemR(layout, &ptr, "error_threshold", 0, NULL, ICON_NONE);
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -192,7 +218,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static void property_error_threshold_define(wmOperatorType *ot)
+static void WM_operator_property_error_threshold(wmOperatorType *ot)
{
PropertyRNA *prop = RNA_def_float(ot->srna,
"error_threshold",
@@ -206,31 +232,6 @@ static void property_error_threshold_define(wmOperatorType *ot)
RNA_def_property_ui_range(prop, FLT_MIN, 10.0f, 0.1f, 5);
}
-static bool error_threshold_display_poll(bContext *C)
-{
- CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
- if (gps->editcurve == NULL) {
- return true;
- }
- }
- CTX_DATA_END;
- return false;
-}
-
-static void select_all_ui(bContext *C, wmOperator *op)
-{
- uiLayout *layout = op->layout;
- PointerRNA ptr;
-
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = ob->data;
-
- if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd) && error_threshold_display_poll(C)) {
- RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
- uiItemR(layout, &ptr, "error_threshold", 0, NULL, ICON_NONE);
- }
-}
-
void GPENCIL_OT_select_all(wmOperatorType *ot)
{
/* identifiers */
@@ -245,10 +246,10 @@ void GPENCIL_OT_select_all(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->ui = select_all_ui;
+ ot->ui = gpencil_select_ui;
WM_operator_properties_select_all(ot);
- property_error_threshold_define(ot);
+ WM_operator_property_error_threshold(ot);
}
/** \} */
@@ -1580,10 +1581,75 @@ static void deselect_all_selected(bContext *C)
/* deselect stroke itself too */
gps->flag &= ~GP_STROKE_SELECT;
}
+ if (gps->editcurve != NULL) {
+ bGPDcurve *gpc = gps->editcurve;
+ for (int i = 0; i < gpc->tot_curve_points; i++) {
+ bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+ BezTriple *bezt = &gpc_pt->bezt;
+ gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+ BEZT_DESEL_ALL(bezt);
+ }
+
+ gpc->flag &= ~GP_CURVE_SELECT;
+ }
}
CTX_DATA_END;
}
+static void gpencil_select_curve_point(bContext *C,
+ const int mval[2],
+ const int radius_squared,
+ bGPDcurve **r_gpc,
+ bGPDcurve_point **r_pt,
+ char *handle)
+{
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ const bool only_selected = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
+
+ int hit_distance = radius_squared;
+
+ GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
+ {
+ for (int i = 0; i < gpc->tot_curve_points; i++) {
+ bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+ BezTriple *bezt = &gpc_pt->bezt;
+
+ if (bezt->hide == 1) {
+ continue;
+ }
+
+ const bool handles_visible = (v3d->overlay.handle_display != CURVE_HANDLE_NONE) &&
+ (!only_selected || BEZT_ISSEL_ANY(bezt));
+
+ /* if the handles are not visible only check ctrl point (vec[1])*/
+ int from = (!handles_visible) ? 1 : 0;
+ int to = (!handles_visible) ? 2 : 3;
+
+ for (int j = from; j < to; j++) {
+ float parent_co[3];
+ mul_v3_m4v3(parent_co, gps_iter.diff_mat, bezt->vec[j]);
+ int screen_co[2];
+ if (ED_view3d_project_int_global(
+ region, parent_co, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
+ V3D_PROJ_RET_OK) {
+ if (!ELEM(V2D_IS_CLIPPED, screen_co[0], screen_co[1])) {
+ const int pt_distance = len_manhattan_v2v2_int(mval, screen_co);
+
+ if (pt_distance <= radius_squared && pt_distance < hit_distance) {
+ *r_gpc = gpc;
+ *r_pt = gpc_pt;
+ *handle = j;
+ hit_distance = pt_distance;
+ }
+ }
+ }
+ }
+ }
+ }
+ GP_EDITABLE_CURVES_END(gps_iter);
+}
+
static int gpencil_select_exec(bContext *C, wmOperator *op)
{
ScrArea *area = CTX_wm_area(C);
@@ -1592,6 +1658,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
const float scale = ts->gp_sculpt.isect_threshold;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
/* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
const float radius = 0.4f * U.widget_unit;
@@ -1603,14 +1670,19 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
bool toggle = RNA_boolean_get(op->ptr, "toggle");
bool whole = RNA_boolean_get(op->ptr, "entire_strokes");
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all") && !use_shift_extend;
+ float error_threshold = RNA_float_get(op->ptr, "error_threshold");
int mval[2] = {0};
+ /* get mouse location */
+ RNA_int_get_array(op->ptr, "location", mval);
GP_SpaceConversion gsc = {NULL};
bGPDlayer *hit_layer = NULL;
bGPDstroke *hit_stroke = NULL;
bGPDspoint *hit_point = NULL;
+ bGPDcurve *hit_curve = NULL;
+ bGPDcurve_point *hit_curve_point = NULL;
int hit_distance = radius_squared;
/* sanity checks */
@@ -1632,73 +1704,77 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
whole = (bool)(ts->gpencil_selectmode_edit == GP_SELECTMODE_STROKE);
}
- /* init space conversion stuff */
- gp_point_conversion_init(C, &gsc);
-
- /* get mouse location */
- RNA_int_get_array(op->ptr, "location", mval);
+ if (is_curve_edit) {
+ char handle = 0;
+ gpencil_select_curve_point(C, mval, radius_squared, &hit_curve, &hit_curve_point, &handle);
+ }
- /* First Pass: Find stroke point which gets hit */
- GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
- bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
- bGPDspoint *pt;
- int i;
+ if (hit_curve_point == NULL) {
+ /* init space conversion stuff */
+ gp_point_conversion_init(C, &gsc);
- /* Check boundbox to speedup. */
- float fmval[2];
- copy_v2fl_v2i(fmval, mval);
- if (!ED_gpencil_stroke_check_collision(
- &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) {
- continue;
- }
+ /* First Pass: Find stroke point which gets hit */
+ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ bGPDspoint *pt;
+ int i;
- /* firstly, check for hit-point */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- int xy[2];
- if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
+ /* Check boundbox to speedup. */
+ float fmval[2];
+ copy_v2fl_v2i(fmval, mval);
+ if (!ED_gpencil_stroke_check_collision(
+ &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) {
continue;
}
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
- gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]);
-
- /* do boundbox check first */
- if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) {
- const int pt_distance = len_manhattan_v2v2_int(mval, xy);
-
- /* check if point is inside */
- if (pt_distance <= radius_squared) {
- /* only use this point if it is a better match than the current hit - T44685 */
- if (pt_distance < hit_distance) {
- hit_layer = gpl;
- hit_stroke = gps_active;
- hit_point = (!is_multiedit) ? pt->runtime.pt_orig : pt;
- hit_distance = pt_distance;
+ /* firstly, check for hit-point */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ int xy[2];
+ if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
+ continue;
+ }
+
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
+ gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]);
+
+ /* do boundbox check first */
+ if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) {
+ const int pt_distance = len_manhattan_v2v2_int(mval, xy);
+
+ /* check if point is inside */
+ if (pt_distance <= radius_squared) {
+ /* only use this point if it is a better match than the current hit - T44685 */
+ if (pt_distance < hit_distance) {
+ hit_layer = gpl;
+ hit_stroke = gps_active;
+ hit_point = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+ hit_distance = pt_distance;
+ }
}
}
}
- }
- if (ELEM(NULL, hit_stroke, hit_point)) {
- /* If nothing hit, check if the mouse is inside any filled stroke.
- * Only check fi
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list