From ef961319e077fb97cde958fd61845afcc775c67c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 26 Mar 2013 06:07:21 +0000 Subject: fix [#34658] GreasePencil eraser deletes strokes through geometry, surfacemode add depth check to grease pencil eraser when xray option is disabled. --- source/blender/editors/gpencil/gpencil_paint.c | 69 +++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 7 deletions(-) (limited to 'source/blender/editors/gpencil') diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index bc68ad8869a..428a46700e3 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -138,7 +138,8 @@ enum { /* Runtime flags */ enum { GP_PAINTFLAG_FIRSTRUN = (1 << 0), /* operator just started */ - GP_PAINTFLAG_STROKEADDED = (1 << 1) + GP_PAINTFLAG_STROKEADDED = (1 << 1), + GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2) }; /* ------ */ @@ -842,6 +843,39 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) } } +/* which which point is infront (result should only be used for comparison) */ +static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) +{ + if (rv3d->is_persp) { + return ED_view3d_calc_zfac(rv3d, co, NULL); + } + else { + return -dot_v3v3(rv3d->viewinv[2], co); + } +} + +static bool gp_stroke_eraser_is_occluded(tGPsdata *p, + const bGPDspoint *pt, const int x, const int y) +{ + if ((p->sa->spacetype == SPACE_VIEW3D) && + (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH)) + { + RegionView3D *rv3d = p->ar->regiondata; + const int mval[2] = {x, y}; + float mval_3d[3]; + + if (ED_view3d_autodist_simple(p->ar, mval, mval_3d, 0, NULL)) { + const float depth_mval = view3d_point_depth(rv3d, mval_3d); + const float depth_pt = view3d_point_depth(rv3d, &pt->x); + + if (depth_pt > depth_mval) { + return true; + } + } + } + return false; +} + /* eraser tool - check if part of stroke occurs within last segment drawn by eraser */ static short gp_stroke_eraser_strokeinside(const int mval[], const int UNUSED(mvalo[]), int rad, int x0, int y0, int x1, int y1) @@ -940,9 +974,13 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, * - this assumes that linewidth is irrelevant */ if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) { - /* if function returns true, break this loop (as no more point to check) */ - if (gp_stroke_eraser_splitdel(gpf, gps, i)) - break; + if ((gp_stroke_eraser_is_occluded(p, pt1, x0, y0) == false) || + (gp_stroke_eraser_is_occluded(p, pt2, x1, y1) == false)) + { + /* if function returns true, break this loop (as no more point to check) */ + if (gp_stroke_eraser_splitdel(gpf, gps, i)) + break; + } } } } @@ -961,7 +999,16 @@ static void gp_stroke_doeraser(tGPsdata *p) rect.ymin = p->mval[1] - p->radius; rect.xmax = p->mval[0] + p->radius; rect.ymax = p->mval[1] + p->radius; - + + if (p->sa->spacetype == SPACE_VIEW3D) { + if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) { + View3D *v3d = p->sa->spacedata.first; + + view3d_region_operator_needs_opengl(p->win, p->ar); + ED_view3d_autodist_init(p->scene, p->ar, v3d, 0); + } + } + /* loop over strokes, checking segments for intersections */ for (gps = gpf->strokes.first; gps; gps = gpn) { gpn = gps->next; @@ -1213,9 +1260,17 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode) /* set 'eraser' for this stroke if using eraser */ p->paintmode = paintmode; - if (p->paintmode == GP_PAINTMODE_ERASER) + if (p->paintmode == GP_PAINTMODE_ERASER) { p->gpd->sbuffer_sflag |= GP_STROKE_ERASER; - + + /* check if we should respect depth while erasing */ + if (p->sa->spacetype == SPACE_VIEW3D) { + if (p->gpl->flag & GP_LAYER_NO_XRAY) { + p->flags |= GP_PAINTFLAG_V3D_ERASER_DEPTH; + } + } + } + /* set 'initial run' flag, which is only used to denote when a new stroke is starting */ p->flags |= GP_PAINTFLAG_FIRSTRUN; -- cgit v1.2.3