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_paint.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_paint.c')
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c77
1 files changed, 48 insertions, 29 deletions
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 2d5491e7569..b833125cf34 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1306,6 +1306,12 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gpd, gps);
+ /* In Multiframe mode, duplicate the stroke in other frames. */
+ if (GPENCIL_MULTIEDIT_SESSIONS_ON(p->gpd)) {
+ const bool tail = (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK);
+ BKE_gpencil_stroke_copy_to_keyframes(gpd, gpl, p->gpf, gps, tail);
+ }
+
gpencil_stroke_added_enable(p);
}
@@ -1323,10 +1329,8 @@ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3])
}
/* only erase stroke points that are visible */
-static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p,
- const bGPDspoint *pt,
- const int x,
- const int y)
+static bool gpencil_stroke_eraser_is_occluded(
+ tGPsdata *p, bGPDlayer *gpl, const bGPDspoint *pt, const int x, const int y)
{
Object *obact = (Object *)p->ownerPtr.data;
Brush *brush = p->brush;
@@ -1343,7 +1347,6 @@ static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p,
if ((gp_settings != NULL) && (p->area->spacetype == SPACE_VIEW3D) &&
(gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) {
RegionView3D *rv3d = p->region->regiondata;
- bGPDlayer *gpl = p->gpl;
const int mval_i[2] = {x, y};
float mval_3d[3];
@@ -1454,6 +1457,7 @@ static void gpencil_stroke_soft_refine(bGPDstroke *gps)
/* eraser tool - evaluation per stroke */
static void gpencil_stroke_eraser_dostroke(tGPsdata *p,
+ bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *gps,
const float mval[2],
@@ -1579,9 +1583,9 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p,
* - this assumes that linewidth is irrelevant
*/
if (gpencil_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) {
- if ((gpencil_stroke_eraser_is_occluded(p, pt0, pc0[0], pc0[1]) == false) ||
- (gpencil_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) ||
- (gpencil_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) {
+ if ((gpencil_stroke_eraser_is_occluded(p, gpl, pt0, pc0[0], pc0[1]) == false) ||
+ (gpencil_stroke_eraser_is_occluded(p, gpl, pt1, pc1[0], pc1[1]) == false) ||
+ (gpencil_stroke_eraser_is_occluded(p, gpl, pt2, pc2[0], pc2[1]) == false)) {
/* Point is affected: */
/* Adjust thickness
* - Influence of eraser falls off with distance from the middle of the eraser
@@ -1683,6 +1687,8 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p,
/* erase strokes which fall under the eraser strokes */
static void gpencil_stroke_doeraser(tGPsdata *p)
{
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(p->gpd);
+
rcti rect;
Brush *brush = p->brush;
Brush *eraser = p->eraser;
@@ -1723,40 +1729,53 @@ static void gpencil_stroke_doeraser(tGPsdata *p)
* on multiple layers...
*/
LISTBASE_FOREACH (bGPDlayer *, gpl, &p->gpd->layers) {
- bGPDframe *gpf = gpl->actframe;
-
/* only affect layer if it's editable (and visible) */
if (BKE_gpencil_layer_is_editable(gpl) == false) {
continue;
}
- if (gpf == NULL) {
+
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+ if (init_gpf == NULL) {
continue;
}
- /* calculate difference matrix */
- BKE_gpencil_layer_transform_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat);
- /* loop over strokes, checking segments for intersections */
- LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
- /* check if the color is editable */
- if (ED_gpencil_stroke_material_editable(p->ob, gpl, gps) == false) {
- continue;
- }
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL) {
+ continue;
+ }
+ /* calculate difference matrix */
+ BKE_gpencil_layer_transform_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat);
+
+ /* loop over strokes, checking segments for intersections */
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_material_editable(p->ob, gpl, gps) == false) {
+ continue;
+ }
- /* Check if the stroke collide with mouse. */
- if (!ED_gpencil_stroke_check_collision(&p->gsc, gps, p->mval, calc_radius, p->diff_mat)) {
- continue;
- }
+ /* Check if the stroke collide with mouse. */
+ if (!ED_gpencil_stroke_check_collision(
+ &p->gsc, gps, p->mval, calc_radius, p->diff_mat)) {
+ continue;
+ }
- /* Not all strokes in the datablock may be valid in the current editor/context
- * (e.g. 2D space strokes in the 3D view, if the same datablock is shared)
- */
- if (ED_gpencil_stroke_can_use_direct(p->area, gps)) {
- gpencil_stroke_eraser_dostroke(p, gpf, gps, p->mval, calc_radius, &rect);
+ /* Not all strokes in the datablock may be valid in the current editor/context
+ * (e.g. 2D space strokes in the 3D view, if the same datablock is shared)
+ */
+ if (ED_gpencil_stroke_can_use_direct(p->area, gps)) {
+ gpencil_stroke_eraser_dostroke(p, gpl, gpf, gps, p->mval, calc_radius, &rect);
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
+ break;
+ }
}
}
}
}
-
/* ******************************************* */
/* Sketching Operator */