Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Vazquez <blendergit@gmail.com>2021-02-08 18:28:42 +0300
committerAntonio Vazquez <blendergit@gmail.com>2021-02-09 18:00:36 +0300
commit1352d81b174726639bbfb6f7aa32dbadf188a8dd (patch)
treeb7bc33114a93c86313b774d8fa05e1214c6844c3 /source/blender/editors/gpencil/gpencil_edit.c
parent5213b18eb2d57153e0e394190af1624401fed74b (diff)
GPencil: Fill tool refactor and Multiframe in Draw mode
This commit is a refactor of the fill tool to solve several problems we had since the first version of the tool. Changes: * The filling speed has been improved for each step of the process with the optimization of each algorithm/function. * New `AutoFit` option to fill areas outside of the viewport. When enable, the total size of the frame is calculated to fit the filling area. * New support multiframe filling. Now it is possible to fill multiple similar frames in one go. * New `Stroke Extension` option to create temporary closing strokes. These strokes can be displayed and adjusted dynamically using wheel mouse or PageUp/Down keys. * Parameter `Resolution` now is named `Precision` and has been moved to topbar. * `Resolution` now has decimals and can be lower than 1 to allow quick filling in storyboarding workflows. Maximum value has been set as 5. * Parameter `Simplify` has been moved to Advanced panel. * Improved fill outline detection. In some cases, the outline penetrated the area to be filled with unexpected results. * Fixes some corner case bugs with infinite loops. As a result of this refactor, also these new functionalities has been added. * New support for multiframe in `Draw` mode. Any drawing in active frame is duplicated to all selected frame. * New multiframe display mode. Keyframes before or after of the active frame are displayed using onion colors. This can be disable using Onion overlay options.
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_edit.c')
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c115
1 files changed, 74 insertions, 41 deletions
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index b5269bbfacf..aeff2acb04d 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -4948,11 +4948,14 @@ static int gpencil_cutter_lasso_select(bContext *C,
GPencilTestFn is_inside_fn,
void *user_data)
{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Object *obact = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
ScrArea *area = CTX_wm_area(C);
ToolSettings *ts = CTX_data_tool_settings(C);
const float scale = ts->gp_sculpt.isect_threshold;
const bool flat_caps = RNA_boolean_get(op->ptr, "flat_caps");
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
bGPDspoint *pt;
GP_SpaceConversion gsc = {NULL};
@@ -4979,57 +4982,87 @@ static int gpencil_cutter_lasso_select(bContext *C,
}
CTX_DATA_END;
- /* select points */
- GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
- int tot_inside = 0;
- const int oldtot = gps->totpoints;
- for (int i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) {
- continue;
- }
- /* convert point coords to screen-space */
- const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
- if (is_inside) {
- tot_inside++;
- changed = true;
- pt->flag |= GP_SPOINT_SELECT;
- gps->flag |= GP_STROKE_SELECT;
- float r_hita[3], r_hitb[3];
- if (gps->totpoints > 1) {
- ED_gpencil_select_stroke_segment(gpd, gpl, gps, pt, true, true, scale, r_hita, r_hitb);
+ /* Select points */
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ if ((gpl->flag & GP_LAYER_LOCKED) || ((gpl->flag & GP_LAYER_HIDE))) {
+ continue;
+ }
+
+ float diff_mat[4][4];
+ BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat);
+
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL) {
+ continue;
}
- /* avoid infinite loops */
- if (gps->totpoints > oldtot) {
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ } /* check if the color is editable */
+ if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) {
+ continue;
+ }
+ int tot_inside = 0;
+ const int oldtot = gps->totpoints;
+ for (int i = 0; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) {
+ continue;
+ }
+ /* convert point coords to screen-space */
+ const bool is_inside = is_inside_fn(gps, pt, &gsc, diff_mat, user_data);
+ if (is_inside) {
+ tot_inside++;
+ changed = true;
+ pt->flag |= GP_SPOINT_SELECT;
+ gps->flag |= GP_STROKE_SELECT;
+ float r_hita[3], r_hitb[3];
+ if (gps->totpoints > 1) {
+ ED_gpencil_select_stroke_segment(
+ gpd, gpl, gps, pt, true, true, scale, r_hita, r_hitb);
+ }
+ /* avoid infinite loops */
+ if (gps->totpoints > oldtot) {
+ break;
+ }
+ }
+ }
+ /* if mark all points inside lasso set to remove all stroke */
+ if ((tot_inside == oldtot) || ((tot_inside == 1) && (oldtot == 2))) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ }
+ }
+ /* if not multiedit, exit loop. */
+ if (!is_multiedit) {
break;
}
}
}
- /* if mark all points inside lasso set to remove all stroke */
- if ((tot_inside == oldtot) || ((tot_inside == 1) && (oldtot == 2))) {
- for (int i = 0; i < gps->totpoints; i++) {
- pt = &gps->points[i];
- pt->flag |= GP_SPOINT_SELECT;
- }
- }
}
- GP_EDITABLE_STROKES_END(gpstroke_iter);
- /* dissolve selected points */
+ /* Dissolve selected points. */
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
- if (gpl->flag & GP_LAYER_LOCKED) {
- continue;
- }
-
- bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
- continue;
- }
- LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
- if (gps->flag & GP_STROKE_SELECT) {
- gpencil_cutter_dissolve(gpd, gpl, gps, flat_caps);
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+ bGPDframe *gpf_act = gpl->actframe;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ gpl->actframe = gpf;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ gpencil_cutter_dissolve(gpd, gpl, gps, flat_caps);
+ }
+ }
+ /* if not multiedit, exit loop. */
+ if (!is_multiedit) {
+ break;
}
}
+ gpl->actframe = gpf_act;
}
/* updates */