diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2021-02-08 18:28:42 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2021-02-09 18:00:36 +0300 |
commit | 1352d81b174726639bbfb6f7aa32dbadf188a8dd (patch) | |
tree | b7bc33114a93c86313b774d8fa05e1214c6844c3 /source/blender/blenkernel | |
parent | 5213b18eb2d57153e0e394190af1624401fed74b (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/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_gpencil.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_gpencil_geom.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/brush.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/gpencil.c | 32 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/gpencil_geom.c | 39 |
5 files changed, 81 insertions, 1 deletions
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index b7fad9c891a..a8caf317467 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -115,6 +115,8 @@ struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src, const bool dup_frames, const bool dup_strokes); void BKE_gpencil_frame_copy_strokes(struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst); +void BKE_gpencil_frame_selected_hash(struct bGPdata *gpd, struct GHash *r_list); + struct bGPDcurve *BKE_gpencil_stroke_curve_duplicate(struct bGPDcurve *gpc_src); struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src, const bool dup_points, diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index 1c86df73d3c..89a794f2df3 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -149,6 +149,11 @@ void BKE_gpencil_stroke_join(struct bGPDstroke *gps_a, struct bGPDstroke *gps_b, const bool leave_gaps, const bool fit_thickness); +void BKE_gpencil_stroke_copy_to_keyframes(struct bGPdata *gpd, + struct bGPDlayer *gpl, + struct bGPDframe *gpf, + struct bGPDstroke *gps, + const bool tail); bool BKE_gpencil_convert_mesh(struct Main *bmain, struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 1ba5571a26b..59ff59b82e0 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -975,7 +975,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) break; } case GP_BRUSH_PRESET_FILL_AREA: { - brush->size = 20.0f; + brush->size = 5.0f; brush->gpencil_settings->fill_leak = 3; brush->gpencil_settings->fill_threshold = 0.1f; @@ -989,6 +989,8 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->draw_smoothlvl = 1; brush->gpencil_settings->draw_subdivide = 1; + brush->gpencil_settings->flag |= GP_BRUSH_FILL_SHOW_EXTENDLINES; + brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL; brush->gpencil_tool = GPAINT_TOOL_FILL; brush->gpencil_settings->vertex_mode = GPPAINT_MODE_FILL; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 0c813c170ad..3d0152a6c7d 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -851,6 +851,7 @@ bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness) gps->mat_nr = mat_idx; + gps->dvert = NULL; gps->editcurve = NULL; return gps; @@ -2606,6 +2607,15 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { if (gpf == act_gpf || (gpf->flag & GP_FRAME_SELECT)) { gpf->runtime.onion_id = 0; + if (do_onion) { + if (gpf->framenum < act_gpf->framenum) { + gpf->runtime.onion_id = -1; + } + else { + gpf->runtime.onion_id = 1; + } + } + if (sta_gpf == NULL) { sta_gpf = gpf; } @@ -2939,4 +2949,26 @@ int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_ return -1; } +/* Create a hash with the list of selected frame number. */ +void BKE_gpencil_frame_selected_hash(bGPdata *gpd, struct GHash *r_list) +{ + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + + LISTBASE_FOREACH (bGPDlayer *, gpl_iter, &gpd->layers) { + if ((gpl != NULL) && (!is_multiedit) && (gpl != gpl_iter)) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_iter->frames) { + if (((gpf == gpl->actframe) && (!is_multiedit)) || + ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (!BLI_ghash_lookup(r_list, POINTER_FROM_INT(gpf->framenum))) { + BLI_ghash_insert(r_list, POINTER_FROM_INT(gpf->framenum), gpf); + } + } + } + } +} + /** \} */ diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 60ffa3c3e73..2ef85439a46 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -3228,6 +3228,45 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, } } +/* Copy the stroke of the frame to all frames selected (except current). */ +void BKE_gpencil_stroke_copy_to_keyframes( + bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, const bool tail) +{ + GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); + BKE_gpencil_frame_selected_hash(gpd, frame_list); + + GHashIterator gh_iter; + GHASH_ITER (gh_iter, frame_list) { + int cfra = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter)); + + if (gpf->framenum != cfra) { + bGPDframe *gpf_new = BKE_gpencil_layer_frame_find(gpl, cfra); + if (gpf_new == NULL) { + gpf_new = BKE_gpencil_frame_addnew(gpl, cfra); + } + + if (gpf_new == NULL) { + continue; + } + + bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, true, true); + if (gps_new == NULL) { + continue; + } + + if (tail) { + BLI_addhead(&gpf_new->strokes, gps_new); + } + else { + BLI_addtail(&gpf_new->strokes, gps_new); + } + } + } + + /* Free hash table. */ + BLI_ghash_free(frame_list, NULL, NULL); +} + /* Stroke Uniform Subdivide ------------------------------------- */ typedef struct tSamplePoint { |