diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2019-08-24 14:46:00 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2019-08-24 14:46:00 +0300 |
commit | 091e7979d314750ff9ecade6e7a3d0c08dba3a1a (patch) | |
tree | bd32d92960dc3333ed06bb3df535ab408a6e0a1a | |
parent | b1ed72f152f041c3f907f9359ba2a7119d256876 (diff) |
GPencil: Use evaluated data in selection
Now the selection is using the position after evaluating the modifiers and makes possible to select a stroke point that has been moved from the original location.
Related to T66294
-rw-r--r-- | source/blender/editors/gpencil/gpencil_intern.h | 54 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_select.c | 100 |
2 files changed, 119 insertions, 35 deletions
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 715665fe6e9..c2a9eae272f 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -639,6 +639,60 @@ struct GP_EditableStrokes_Iter { ((flag & (GP_SCULPT_MASK_SELECTMODE_POINT | GP_SCULPT_MASK_SELECTMODE_STROKE | \ GP_SCULPT_MASK_SELECTMODE_SEGMENT))) +/** + * Iterate over all editable strokes using evaluated data in the current context, + * stopping on each usable layer + stroke pair (i.e. gpl and gps) + * to perform some operations on the stroke. + * + * \param gpl: The identifier to use for the layer of the stroke being processed. + * Choose a suitable value to avoid name clashes. + * \param gps: The identifier to use for current stroke being processed. + * Choose a suitable value to avoid name clashes. + */ +#define GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \ + { \ + struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \ + Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \ + Object *obact_ = CTX_data_active_object(C); \ + Object *obeval_ = DEG_get_evaluated_object(depsgraph_, obact_); \ + bGPdata *gpd_ = CTX_data_gpencil_data(C); \ + const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \ + int idx_eval = 0; \ + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { \ + if (gpencil_layer_is_editable(gpl)) { \ + bGPDframe *init_gpf_ = gpl->actframe; \ + if (is_multiedit_) { \ + init_gpf_ = gpl->frames.first; \ + } \ + for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ + if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ + ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \ + invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ + /* get evaluated frame with modifiers applied */ \ + bGPDframe *gpf_eval_ = &obeval_->runtime.gpencil_evaluated_frames[idx_eval]; \ + /* loop over strokes */ \ + for (bGPDstroke *gps = gpf_eval_->strokes.first; gps; gps = gps->next) { \ + /* skip strokes that are invalid for current view */ \ + if (ED_gpencil_stroke_can_use(C, gps) == false) \ + continue; \ + /* check if the color is editable */ \ + if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) \ + continue; \ + /* ... Do Stuff With Strokes ... */ + +#define GP_EVALUATED_STROKES_END(gpstroke_iter) \ + } \ + } \ + if (!is_multiedit_) { \ + break; \ + } \ + } \ + } \ + idx_eval++; \ + } \ + } \ + (void)0 + /* ****************************************************** */ #endif /* __GPENCIL_INTERN_H__ */ diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 71ccf740153..7225bf43fbd 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -825,6 +825,7 @@ static bool gp_stroke_do_circle_sel(bGPDlayer *gpl, { bGPDspoint *pt1 = NULL; bGPDspoint *pt2 = NULL; + bGPDstroke *gps_orig = gps->runtime.gps_orig; int x0 = 0, y0 = 0, x1 = 0, y1 = 0; int i; bool changed = false; @@ -840,12 +841,12 @@ static bool gp_stroke_do_circle_sel(bGPDlayer *gpl, if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) { /* change selection */ if (select) { - gps->points->flag |= GP_SPOINT_SELECT; - gps->flag |= GP_STROKE_SELECT; + gps_orig->points->flag |= GP_SPOINT_SELECT; + gps_orig->flag |= GP_STROKE_SELECT; } else { - gps->points->flag &= ~GP_SPOINT_SELECT; - gps->flag &= ~GP_STROKE_SELECT; + gps_orig->points->flag &= ~GP_SPOINT_SELECT; + gps_orig->flag &= ~GP_STROKE_SELECT; } return true; @@ -885,15 +886,21 @@ static bool gp_stroke_do_circle_sel(bGPDlayer *gpl, */ hit = true; if (select) { - pt1->flag |= GP_SPOINT_SELECT; - pt2->flag |= GP_SPOINT_SELECT; - + if (pt1->runtime.pt_orig != NULL) { + pt1->runtime.pt_orig->flag |= GP_SPOINT_SELECT; + } + if (pt2->runtime.pt_orig != NULL) { + pt2->runtime.pt_orig->flag |= GP_SPOINT_SELECT; + } changed = true; } else { - pt1->flag &= ~GP_SPOINT_SELECT; - pt2->flag &= ~GP_SPOINT_SELECT; - + if (pt1->runtime.pt_orig != NULL) { + pt1->runtime.pt_orig->flag &= ~GP_SPOINT_SELECT; + } + if (pt2->runtime.pt_orig != NULL) { + pt2->runtime.pt_orig->flag &= ~GP_SPOINT_SELECT; + } changed = true; } } @@ -907,24 +914,28 @@ static bool gp_stroke_do_circle_sel(bGPDlayer *gpl, /* if stroke mode expand selection */ if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) { for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) { - if (select) { - pt1->flag |= GP_SPOINT_SELECT; - } - else { - pt1->flag &= ~GP_SPOINT_SELECT; + if (pt1->runtime.pt_orig != NULL) { + if (select) { + pt1->runtime.pt_orig->flag |= GP_SPOINT_SELECT; + } + else { + pt1->runtime.pt_orig->flag &= ~GP_SPOINT_SELECT; + } } } } /* expand selection to segment */ - if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select)) { + if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select) && + (pt1->runtime.pt_orig != NULL)) { float r_hita[3], r_hitb[3]; bool hit_select = (bool)(pt1->flag & GP_SPOINT_SELECT); - ED_gpencil_select_stroke_segment(gpl, gps, pt1, hit_select, false, scale, r_hita, r_hitb); + ED_gpencil_select_stroke_segment( + gpl, gps_orig, pt1->runtime.pt_orig, hit_select, false, scale, r_hita, r_hitb); } /* Ensure that stroke selection is in sync with its points */ - BKE_gpencil_stroke_sync_selection(gps); + BKE_gpencil_stroke_sync_selection(gps_orig); } return changed; @@ -982,11 +993,12 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) rect.ymax = my + radius; /* find visible strokes, and select if hit */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { + GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) + { changed |= gp_stroke_do_circle_sel( gpl, gps, &gsc, mx, my, radius, select, &rect, gpstroke_iter.diff_mat, selectmode, scale); } - GP_EDITABLE_STROKES_END(gpstroke_iter); + GP_EVALUATED_STROKES_END(gpstroke_iter); /* updates */ if (changed) { @@ -1090,27 +1102,38 @@ static int gpencil_generic_select_exec(bContext *C, } /* select/deselect points */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { + GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) + { bGPDspoint *pt; int i; bool hit = false; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (pt->runtime.pt_orig == NULL) { + continue; + } + /* convert point coords to screenspace */ const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data); if (strokemode == false) { - const bool is_select = (pt->flag & GP_SPOINT_SELECT) != 0; + const bool is_select = (pt->runtime.pt_orig->flag & GP_SPOINT_SELECT) != 0; const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(pt->flag, sel_op_result, GP_SPOINT_SELECT); + SET_FLAG_FROM_TEST(pt->runtime.pt_orig->flag, sel_op_result, GP_SPOINT_SELECT); changed = true; /* expand selection to segment */ if ((sel_op_result != -1) && (segmentmode)) { - bool hit_select = (bool)(pt->flag & GP_SPOINT_SELECT); + bool hit_select = (bool)(pt->runtime.pt_orig->flag & GP_SPOINT_SELECT); float r_hita[3], r_hitb[3]; - ED_gpencil_select_stroke_segment( - gpl, gps, pt, hit_select, false, scale, r_hita, r_hitb); + ED_gpencil_select_stroke_segment(gpl, + gps->runtime.gps_orig, + pt->runtime.pt_orig, + hit_select, + false, + scale, + r_hita, + r_hitb); } } } @@ -1124,16 +1147,19 @@ static int gpencil_generic_select_exec(bContext *C, /* if stroke mode expand selection */ if (strokemode) { - const bool is_select = BKE_gpencil_stroke_select_check(gps); + const bool is_select = BKE_gpencil_stroke_select_check(gps->runtime.gps_orig); const bool is_inside = hit; const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (pt->runtime.pt_orig == NULL) { + continue; + } if (sel_op_result) { - pt->flag |= GP_SPOINT_SELECT; + pt->runtime.pt_orig->flag |= GP_SPOINT_SELECT; } else { - pt->flag &= ~GP_SPOINT_SELECT; + pt->runtime.pt_orig->flag &= ~GP_SPOINT_SELECT; } } changed = true; @@ -1141,9 +1167,9 @@ static int gpencil_generic_select_exec(bContext *C, } /* Ensure that stroke selection is in sync with its points */ - BKE_gpencil_stroke_sync_selection(gps); + BKE_gpencil_stroke_sync_selection(gps->runtime.gps_orig); } - GP_EDITABLE_STROKES_END(gpstroke_iter); + GP_EVALUATED_STROKES_END(gpstroke_iter); /* if paint mode,delete selected points */ if (gpd->flag & GP_DATA_STROKE_PAINTMODE) { @@ -1365,13 +1391,17 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) /* First Pass: Find stroke point which gets hit */ /* XXX: maybe we should go from the top of the stack down instead... */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { + GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, 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 (pt->runtime.pt_orig == NULL) { + continue; + } bGPDspoint pt2; gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2); @@ -1386,15 +1416,15 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) /* 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; - hit_point = pt; + hit_stroke = gps->runtime.gps_orig; + hit_point = pt->runtime.pt_orig; hit_distance = pt_distance; } } } } } - GP_EDITABLE_STROKES_END(gpstroke_iter); + GP_EVALUATED_STROKES_END(gpstroke_iter); /* Abort if nothing hit... */ if (ELEM(NULL, hit_stroke, hit_point)) { |