diff options
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_paint.c')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_paint.c | 176 |
1 files changed, 82 insertions, 94 deletions
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 16262765888..432292c259d 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -281,7 +281,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] /* method taken from editview.c - mouse_cursor() */ /* TODO, use ED_view3d_project_float_global */ - if (ED_view3d_project_int_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) { + if (ED_view3d_project_int_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { VECSUB2D(mval_f, mval_prj, mval); ED_view3d_win_to_delta(p->ar, mval_f, dvec); sub_v3_v3v3(out, rvec, dvec); @@ -397,8 +397,10 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) pts = &gps->points[gps->totpoints - 1]; - /* special case for poly lines: normally, depth is needed only when creating new stroke from buffer, - * but poly lines are converting to stroke instantly, so initialize depth buffer before converting coordinates + /* special case for poly lines: normally, + * depth is needed only when creating new stroke from buffer, + * but poly lines are converting to stroke instantly, + * so initialize depth buffer before converting coordinates */ if (gpencil_project_check(p)) { View3D *v3d = p->sa->spacedata.first; @@ -536,7 +538,7 @@ static void gp_stroke_simplify(tGPsdata *p) j += 2; } - } + } /* free old buffer */ MEM_freeN(old_points); @@ -787,13 +789,49 @@ static short gp_stroke_eraser_strokeinside(const int mval[], const int UNUSED(mv int rad, int x0, int y0, int x1, int y1) { /* simple within-radius check for now */ - if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1)) - return 1; + const float mval_fl[2] = {mval[0], mval[1]}; + const float screen_co_a[2] = {x0, y0}; + const float screen_co_b[2] = {x1, y1}; + + if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) { + return TRUE; + } /* not inside */ - return 0; + return FALSE; } +static void gp_point_to_xy(ARegion *ar, View2D *v2d, rctf *subrect, bGPDstroke *gps, bGPDspoint *pt, + int *r_x, int *r_y) +{ + int xyval[2]; + + if (gps->flag & GP_STROKE_3DSPACE) { + if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + *r_x = xyval[0]; + *r_y = xyval[1]; + } + else { + *r_x = V2D_IS_CLIPPED; + *r_y = V2D_IS_CLIPPED; + } + } + else if (gps->flag & GP_STROKE_2DSPACE) { + UI_view2d_view_to_region(v2d, pt->x, pt->y, r_x, r_y); + } + else { + if (subrect == NULL) { /* normal 3D view */ + *r_x = (int)(pt->x / 100 * ar->winx); + *r_y = (int)(pt->y / 100 * ar->winy); + } + else { /* camera view, use subrect */ + *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin; + *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin; + } + } +} + + /* eraser tool - evaluation per stroke */ // TODO: this could really do with some optimization (KD-Tree/BVH?) static void gp_stroke_eraser_dostroke(tGPsdata *p, @@ -802,7 +840,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, { bGPDspoint *pt1, *pt2; int x0 = 0, y0 = 0, x1 = 0, y1 = 0; - int xyval[2]; int i; if (gps->totpoints == 0) { @@ -812,33 +849,11 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, BLI_freelinkN(&gpf->strokes, gps); } else if (gps->totpoints == 1) { - /* get coordinates */ - if (gps->flag & GP_STROKE_3DSPACE) { - if (ED_view3d_project_int_global(p->ar, &gps->points->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) { - x0 = xyval[0]; - y0 = xyval[1]; - } - else { - x0 = V2D_IS_CLIPPED; - y0 = V2D_IS_CLIPPED; - } - } - else if (gps->flag & GP_STROKE_2DSPACE) { - UI_view2d_view_to_region(p->v2d, gps->points->x, gps->points->y, &x0, &y0); - } - else { - if (p->subrect == NULL) { /* normal 3D view */ - x0 = (int)(gps->points->x / 100 * p->ar->winx); - y0 = (int)(gps->points->y / 100 * p->ar->winy); - } - else { /* camera view, use subrect */ - x0 = (int)((gps->points->x / 100) * BLI_rctf_size_x(p->subrect)) + p->subrect->xmin; - y0 = (int)((gps->points->y / 100) * BLI_rctf_size_y(p->subrect)) + p->subrect->ymin; - } - } + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, gps->points, &x0, &y0); /* do boundbox check first */ - if (BLI_rcti_isect_pt(rect, x0, y0)) { + + if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ if (((x0 - mval[0]) * (x0 - mval[0]) + (y0 - mval[1]) * (y0 - mval[1])) <= rad * rad) { /* free stroke */ @@ -847,7 +862,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, } } } - else { + else { /* loop over the points in the stroke, checking for intersections * - an intersection will require the stroke to be split */ @@ -855,48 +870,13 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* get points to work with */ pt1 = gps->points + i; pt2 = gps->points + i + 1; - - /* get coordinates */ - if (gps->flag & GP_STROKE_3DSPACE) { - if (ED_view3d_project_int_global(p->ar, &pt1->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) { - x0 = xyval[0]; - y0 = xyval[1]; - } - else { - x0 = V2D_IS_CLIPPED; - y0 = V2D_IS_CLIPPED; - } - if (ED_view3d_project_int_global(p->ar, &pt2->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_SUCCESS) { - x1 = xyval[0]; - y1 = xyval[1]; - } - else { - x1 = V2D_IS_CLIPPED; - y1 = V2D_IS_CLIPPED; - } - } - else if (gps->flag & GP_STROKE_2DSPACE) { - UI_view2d_view_to_region(p->v2d, pt1->x, pt1->y, &x0, &y0); - - UI_view2d_view_to_region(p->v2d, pt2->x, pt2->y, &x1, &y1); - } - else { - if (p->subrect == NULL) { /* normal 3D view */ - x0 = (int)(pt1->x / 100 * p->ar->winx); - y0 = (int)(pt1->y / 100 * p->ar->winy); - x1 = (int)(pt2->x / 100 * p->ar->winx); - y1 = (int)(pt2->y / 100 * p->ar->winy); - } - else { /* camera view, use subrect */ - x0 = (int)((pt1->x / 100) * BLI_rctf_size_x(p->subrect)) + p->subrect->xmin; - y0 = (int)((pt1->y / 100) * BLI_rctf_size_y(p->subrect)) + p->subrect->ymin; - x1 = (int)((pt2->x / 100) * BLI_rctf_size_x(p->subrect)) + p->subrect->xmin; - y1 = (int)((pt2->y / 100) * BLI_rctf_size_y(p->subrect)) + p->subrect->ymin; - } - } - + + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt1, &x0, &y0); + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt2, &x1, &y1); + /* check that point segment of the boundbox of the eraser stroke */ - if (BLI_rcti_isect_pt(rect, x0, y0) || BLI_rcti_isect_pt(rect, x1, y1)) { + if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) || + ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) { /* check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant @@ -981,8 +961,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) /* supported views first */ case SPACE_VIEW3D: { - // View3D *v3d= curarea->spacedata.first; - // RegionView3D *rv3d= ar->regiondata; + // View3D *v3d = curarea->spacedata.first; + // RegionView3D *rv3d = ar->regiondata; /* set current area * - must verify that region data is 3D-view (and not something else) @@ -1001,7 +981,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) case SPACE_NODE: { - //SpaceNode *snode= curarea->spacedata.first; + //SpaceNode *snode = curarea->spacedata.first; /* set current area */ p->sa = curarea; @@ -1029,7 +1009,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) break; case SPACE_IMAGE: { - //SpaceImage *sima= curarea->spacedata.first; + //SpaceImage *sima = curarea->spacedata.first; /* set the current area */ p->sa = curarea; @@ -1232,7 +1212,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode) /* make strokes be drawn in screen space */ p->gpd->sbuffer_sflag &= ~GP_STROKE_2DSPACE; p->gpd->flag &= ~GP_DATA_VIEWALIGN; - } + } else p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE; } @@ -1358,7 +1338,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) gp_session_cleanup(p); /* finally, free the temp data */ - MEM_freeN(p); + MEM_freeN(p); } op->customdata = NULL; @@ -1419,13 +1399,17 @@ static void gpencil_draw_status_indicators(tGPsdata *p) /* print status info */ switch (p->paintmode) { case GP_PAINTMODE_ERASER: - ED_area_headerprint(p->sa, "Grease Pencil Erase Session: Hold and drag LMB or RMB to erase | ESC/Enter to end"); + ED_area_headerprint(p->sa, + "Grease Pencil Erase Session: Hold and drag LMB or RMB to erase |" + " ESC/Enter to end"); break; case GP_PAINTMODE_DRAW_STRAIGHT: - ED_area_headerprint(p->sa, "Grease Pencil Line Session: Hold and drag LMB to draw | ESC/Enter to end"); + ED_area_headerprint(p->sa, "Grease Pencil Line Session: Hold and drag LMB to draw | " + "ESC/Enter to end"); break; case GP_PAINTMODE_DRAW: - ED_area_headerprint(p->sa, "Grease Pencil Freehand Session: Hold and drag LMB to draw | ESC/Enter to end"); + ED_area_headerprint(p->sa, "Grease Pencil Freehand Session: Hold and drag LMB to draw | " + "ESC/Enter to end"); break; default: /* unhandled future cases */ @@ -1660,7 +1644,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) * painting should start immediately. Otherwise, this was called from a toolbar, in which * case we should wait for the mouse to be clicked. */ - if (event->type) { + if (event->val == KM_PRESS) { /* hotkey invoked - start drawing */ //printf("\tGP - set first spot\n"); p->status = GP_STATUS_PAINTING; @@ -1701,7 +1685,8 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) //printf("\t\tGP - start stroke\n"); /* we may need to set up paint env again if we're resuming */ - /* XXX: watch it with the paintmode! in future, it'd be nice to allow changing paint-mode when in sketching-sessions */ + /* XXX: watch it with the paintmode! in future, + * it'd be nice to allow changing paint-mode when in sketching-sessions */ /* XXX: with tablet events, we may event want to check for eraser here, for nicer tablet support */ if (gp_session_initdata(C, p)) @@ -1734,7 +1719,7 @@ static void gpencil_stroke_end(wmOperator *op) static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p = op->customdata; - int estate = OPERATOR_PASS_THROUGH; /* default exit state - not handled, so let others have a share of the pie */ + int estate = OPERATOR_RUNNING_MODAL; /* default exit state - we don't pass on events, GP is used with key-modifiers */ /* if (event->type == NDOF_MOTION) * return OPERATOR_PASS_THROUGH; @@ -1801,7 +1786,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) if (p->status == GP_STATUS_ERROR) { estate = OPERATOR_CANCELLED; } - } + } else { p->status = GP_STATUS_IDLING; } @@ -1885,7 +1870,10 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH: /* event doesn't need to be handled */ - //printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n", event->type, event->type == MIDDLEMOUSE, event->type==MOUSEMOVE); +#if 0 + printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n", + event->type, event->type == MIDDLEMOUSE, event->type==MOUSEMOVE); +#endif break; } @@ -1896,10 +1884,10 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* ------------------------------- */ static EnumPropertyItem prop_gpencil_drawmodes[] = { - {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", ""}, - {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 0, "Draw Straight Lines", ""}, - {GP_PAINTMODE_DRAW_POLY, "DRAW_POLY", 0, "Draw Poly Line", ""}, - {GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", ""}, + {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", "Draw freehand stroke(s)"}, + {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 0, "Draw Straight Lines", "Draw straight line segment(s)"}, + {GP_PAINTMODE_DRAW_POLY, "DRAW_POLY", 0, "Draw Poly Line", "Click to place endpoints of straight line segments (connected)"}, + {GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", "Erase Grease Pencil strokes"}, {0, NULL, 0, NULL, NULL} }; @@ -1921,7 +1909,7 @@ void GPENCIL_OT_draw(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; /* settings for drawing */ - RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements"); + ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements"); RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); } |