diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2011-09-06 12:30:17 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2011-09-06 12:30:17 +0400 |
commit | 32287bebe82615b8500ef0196b7b780745147835 (patch) | |
tree | 188b45ca42d95d3e21a588f3fe5af391a13b31cb /source/blender/editors/gpencil/gpencil_paint.c | |
parent | 82f7a5e3a25492eb58a0c0ec1933309c37d17e28 (diff) |
New grease pencil mode: poly line drawing
- It's like sketch mode for lines, but you're specifying line knots
by clicking on position you want to add next knot.
- View can be navigated between knots creation.
- Holding LMB down and sliding mouse will lead to new segment preview
so it can be created more accurate.
Additional change: fixed GP->Bezier conversion. Last point used to
be ignored in this operator.
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_paint.c')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_paint.c | 130 |
1 files changed, 103 insertions, 27 deletions
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index df5fa65c980..460408c6269 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -124,6 +124,7 @@ enum { /* Runtime flags */ enum { GP_PAINTFLAG_FIRSTRUN = (1<<0), /* operator just started */ + GP_PAINTFLAG_STROKEADDED = (1<<1) /* stroke was already added during draw session */ }; /* ------ */ @@ -375,6 +376,43 @@ static short gp_stroke_addpoint (tGPsdata *p, const int mval[2], float pressure) else return GP_STROKEADD_NORMAL; } + else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { + /* get pointer to destination point */ + pt= (tGPspoint *)(gpd->sbuffer); + + /* store settings */ + pt->x= mval[0]; + pt->y= mval[1]; + pt->pressure= pressure; + + /* if there's stroke fir this poly line session add (or replace last) point + to stroke. This allows to draw lines more interactively (see new segment + during mouse slide, i.e.) */ + if (p->flags & GP_PAINTFLAG_STROKEADDED) { + bGPDstroke *gps= p->gpf->strokes.last; + bGPDspoint *pts; + + /* first time point is adding to temporary buffer -- need to allocate new point in stroke */ + if (gpd->sbuffer_size == 0) { + gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint)*(gps->totpoints+1)); + gps->totpoints++; + } + + pts = &gps->points[gps->totpoints-1]; + + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL); + + /* copy pressure */ + pts->pressure= pt->pressure; + } + + /* increment counters */ + if (gpd->sbuffer_size == 0) + gpd->sbuffer_size++; + + return GP_STROKEADD_NORMAL; + } /* return invalid state for now... */ return GP_STROKEADD_INVALID; @@ -395,7 +433,7 @@ static void gp_stroke_smooth (tGPsdata *p) int i=0, cmx=gpd->sbuffer_size; /* only smooth if smoothing is enabled, and we're not doing a straight line */ - if (!(U.gp_settings & GP_PAINT_DOSMOOTH) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)) + if (!(U.gp_settings & GP_PAINT_DOSMOOTH) || ELEM(p->paintmode, GP_PAINTMODE_DRAW_STRAIGHT, GP_PAINTMODE_DRAW_POLY)) return; /* don't try if less than 2 points in buffer */ @@ -527,17 +565,28 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) return; } + /* special case for poly line -- for already added stroke during session + coordinates are getting added to stroke immediatelly to allow more + interactive behavior */ + if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { + if (p->flags & GP_PAINTFLAG_STROKEADDED) + return; + } + /* allocate memory for a new stroke */ gps= MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); - /* allocate enough memory for a continuous array for storage points */ - pt= gps->points= MEM_callocN(sizeof(bGPDspoint)*totelem, "gp_stroke_points"); - /* copy appropriate settings for stroke */ gps->totpoints= totelem; gps->thickness= p->gpl->thickness; gps->flag= gpd->sbuffer_sflag; + /* allocate enough memory for a continuous array for storage points */ + gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points"); + + /* set pointer to first non-initialized point */ + pt= gps->points + (gps->totpoints - totelem); + /* copy points from the buffer to the stroke */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only -> only endpoints */ @@ -565,6 +614,16 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) pt->pressure= ptc->pressure; } } + else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { + /* first point */ + ptc= gpd->sbuffer; + + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + + /* copy pressure */ + pt->pressure= ptc->pressure; + } else { float *depth_arr= NULL; @@ -643,6 +702,8 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) MEM_freeN(depth_arr); } + p->flags |= GP_PAINTFLAG_STROKEADDED; + /* add stroke to frame */ BLI_addtail(&p->gpf->strokes, gps); } @@ -891,8 +952,10 @@ static void gp_session_validatebuffer (tGPsdata *p) bGPdata *gpd= p->gpd; /* clear memory of buffer (or allocate it if starting a new session) */ - if (gpd->sbuffer) + if (gpd->sbuffer) { + //printf("\t\tGP - reset sbuffer\n"); memset(gpd->sbuffer, 0, sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX); + } else { //printf("\t\tGP - allocate sbuffer\n"); gpd->sbuffer= MEM_callocN(sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer"); @@ -905,24 +968,21 @@ static void gp_session_validatebuffer (tGPsdata *p) gpd->sbuffer_sflag= 0; } -/* init new painting session */ -static tGPsdata *gp_session_initpaint (bContext *C) +/* (re)init new painting data */ +static int gp_session_initdata (bContext *C, tGPsdata *p) { - tGPsdata *p = NULL; bGPdata **gpd_ptr = NULL; ScrArea *curarea= CTX_wm_area(C); ARegion *ar= CTX_wm_region(C); /* make sure the active view (at the starting time) is a 3d-view */ if (curarea == NULL) { + p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: No active view for painting \n"); - return NULL; + return 0; } - /* create new context data */ - p= MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data"); - /* pass on current scene and window */ p->scene= CTX_data_scene(C); p->win= CTX_wm_window(C); @@ -944,7 +1004,7 @@ static tGPsdata *gp_session_initpaint (bContext *C) p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: 3D-View active region doesn't have any region data, so cannot be drawable \n"); - return p; + return 0; } #if 0 // XXX will this sort of antiquated stuff be restored? @@ -953,7 +1013,7 @@ static tGPsdata *gp_session_initpaint (bContext *C) p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: In active view, Grease Pencil not shown \n"); - return p; + return 0; } #endif } @@ -974,7 +1034,7 @@ static tGPsdata *gp_session_initpaint (bContext *C) p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: In active view, Grease Pencil not shown \n"); - return; + return 0; } #endif } @@ -994,13 +1054,13 @@ static tGPsdata *gp_session_initpaint (bContext *C) p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil \n"); - return; + return 0; } if ((sseq->flag & SEQ_DRAW_GPENCIL)==0) { p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: In active view, Grease Pencil not shown \n"); - return; + return 0; } } break; @@ -1021,7 +1081,7 @@ static tGPsdata *gp_session_initpaint (bContext *C) p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: In active view, Grease Pencil not shown \n"); - return p; + return 0; } #endif } @@ -1033,7 +1093,7 @@ static tGPsdata *gp_session_initpaint (bContext *C) p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: Active view not appropriate for Grease Pencil drawing \n"); - return p; + return 0; } break; } @@ -1044,7 +1104,7 @@ static tGPsdata *gp_session_initpaint (bContext *C) p->status= GP_STATUS_ERROR; if (G.f & G_DEBUG) printf("Error: Current context doesn't allow for any Grease Pencil data \n"); - return p; + return 0; } else { /* if no existing GPencil block exists, add one */ @@ -1067,6 +1127,19 @@ static tGPsdata *gp_session_initpaint (bContext *C) p->im2d_settings.sizex= 1; p->im2d_settings.sizey= 1; #endif + + return 1; +} + +/* init new painting session */ +static tGPsdata *gp_session_initpaint (bContext *C) +{ + tGPsdata *p = NULL; + + /* create new context data */ + p= MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data"); + + gp_session_initdata(C, p); /* return context data for running paint operator */ return p; @@ -1629,17 +1702,14 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) p->status= GP_STATUS_ERROR; } - /* free pointer used by previous stroke */ - if(p) - MEM_freeN(p); - //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: with tablet events, we may event want to check for eraser here, for nicer tablet support - gpencil_draw_init(C, op); + if (gp_session_initdata(C, p)) + gp_paint_initstroke(p, p->paintmode); p= op->customdata; @@ -1698,10 +1768,15 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event) if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE)) { /* if painting, end stroke */ if (p->status == GP_STATUS_PAINTING) { + int sketch= 0; /* basically, this should be mouse-button up = end stroke * BUT what happens next depends on whether we 'painting sessions' is enabled */ - if (GPENCIL_SKETCH_SESSIONS_ON(p->scene)) { + sketch|= GPENCIL_SKETCH_SESSIONS_ON(p->scene); + /* polyline drawig is also 'sketching' -- all knots should be added during one session */ + sketch|= p->paintmode == GP_PAINTMODE_DRAW_POLY; + + if (sketch) { /* end stroke only, and then wait to resume painting soon */ //printf("\t\tGP - end stroke only\n"); gpencil_stroke_end(op); @@ -1710,7 +1785,7 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event) estate = OPERATOR_RUNNING_MODAL; /* stroke could be smoothed, send notifier to refresh screen */ - ED_region_tag_redraw(p->ar); + WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL); } else { //printf("\t\tGP - end of stroke + op\n"); @@ -1794,6 +1869,7 @@ 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, "Dtaw Poly Line", ""}, {GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", ""}, {0, NULL, 0, NULL, NULL} }; |