diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-08-29 05:54:10 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-08-29 05:54:10 +0400 |
commit | f46f6dc7ba32411a8031a243bba635c8cc3ade29 (patch) | |
tree | 0d1eef91b9a562990f209c13b30ba96c2fe7b2b7 /source/blender/editors/gpencil | |
parent | 732844bb28f1ad7b14d91455ad24df3d3be86e0c (diff) |
Grease Pencil: Toolbar Compatability Fixes
* When starting Grease Pencil from the toolbar, strokes are now started only when a click-drag begins.
* Made the 'straight-lines' option an RNA property for the operator
* Added an exec() callback and relevant stroke-collection stuff so that interactive redo/changing settings can work.
WARNING: this is highly unstable here - keeps crashing though I cannot determine the cause yet.
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_paint.c | 249 |
1 files changed, 178 insertions, 71 deletions
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index d6bdea2db55..445d9ae346d 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -115,7 +115,8 @@ typedef struct tGPsdata { /* values for tGPsdata->status */ enum { - GP_STATUS_NORMAL = 0, /* running normally */ + GP_STATUS_IDLING = 0, /* stroke isn't in progress yet */ + GP_STATUS_PAINTING, /* a stroke is in progress */ GP_STATUS_ERROR, /* something wasn't correctly set up */ GP_STATUS_DONE /* painting done */ }; @@ -196,7 +197,7 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) { View3D *v3d= p->sa->spacedata.first; const short mx=mval[0], my=mval[1]; - float *fp= give_cursor(p->scene, v3d); // XXX NULL could be v3d + float *fp= give_cursor(p->scene, v3d); float dvec[3]; /* Current method just converts each point in screen-coordinates to @@ -727,10 +728,19 @@ static tGPsdata *gp_session_initpaint (bContext *C) { //View3D *v3d= curarea->spacedata.first; - /* set current area */ + /* set current area + * - must verify that region data is 3D-view (and not something else) + */ p->sa= curarea; p->ar= ar; + if (ar->regiondata == NULL) { + 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; + } + #if 0 // XXX will this sort of antiquated stuff be restored? /* check that gpencil data is allowed to be drawn */ if ((v3d->flag2 & V3D_DISPGP)==0) { @@ -1002,8 +1012,8 @@ static void gp_paint_cleanup (tGPsdata *p) static int gpencil_draw_init (bContext *C, wmOperator *op) { tGPsdata *p; - wmWindow *win= CTX_wm_window(C); int paintmode= RNA_enum_get(op->ptr, "mode"); + int straightLines= RNA_boolean_get(op->ptr, "straight_lines"); /* check context */ p= op->customdata= gp_session_initpaint(C); @@ -1023,11 +1033,9 @@ static int gpencil_draw_init (bContext *C, wmOperator *op) /* radius for eraser circle is defined in userprefs now */ p->radius= U.gp_eraser; - /* set cursor */ - if (p->paintmode == GP_PAINTMODE_ERASER) - WM_cursor_modal(win, BC_CROSSCURSOR); // XXX need a better cursor - else - WM_cursor_modal(win, BC_PAINTBRUSHCURSOR); + /* set line-drawing settings (straight or freehand lines) */ + if (straightLines) + p->flags |= GP_PAINTFLAG_STRAIGHTLINES; /* everything is now setup ok */ return 1; @@ -1069,10 +1077,57 @@ static int gpencil_draw_cancel (bContext *C, wmOperator *op) /* ------------------------------- */ +/* create a new stroke point at the point indicated by the painting context */ +static void gpencil_draw_apply (bContext *C, wmOperator *op, tGPsdata *p) +{ + /* handle drawing/erasing -> test for erasing first */ + if (p->paintmode == GP_PAINTMODE_ERASER) { + /* do 'live' erasing now */ + gp_stroke_doeraser(p); + + /* store used values */ + p->mvalo[0]= p->mval[0]; + p->mvalo[1]= p->mval[1]; + p->opressure= p->pressure; + } + /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ + else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { + /* try to add point */ + short ok= gp_stroke_addpoint(p, p->mval, p->pressure); + + /* handle errors while adding point */ + if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { + /* finish off old stroke */ + gp_paint_strokeend(p); + + /* start a new stroke, starting from previous point */ + gp_stroke_addpoint(p, p->mvalo, p->opressure); + ok= gp_stroke_addpoint(p, p->mval, p->pressure); + } + else if (ok == GP_STROKEADD_INVALID) { + /* the painting operation cannot continue... */ + BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke"); + p->status = GP_STATUS_ERROR; + + if (G.f & G_DEBUG) + printf("Error: Grease-Pencil Paint - Add Point Invalid \n"); + // XXX break! + } + + /* store used values */ + p->mvalo[0]= p->mval[0]; + p->mvalo[1]= p->mval[1]; + p->opressure= p->pressure; + } +} + +/* handle draw event */ static void gpencil_draw_apply_event (bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p= op->customdata; ARegion *ar= p->ar; + PointerRNA itemptr; + float mousef[2]; int tablet=0; /* convert from window-space to area-space mouse coordintes */ @@ -1107,56 +1162,86 @@ static void gpencil_draw_apply_event (bContext *C, wmOperator *op, wmEvent *even return; } + /* fill in stroke data (not actually used directly by gpencil_draw_apply) */ + RNA_collection_add(op->ptr, "stroke", &itemptr); + + mousef[0]= p->mval[0]; + mousef[1]= p->mval[1]; + RNA_float_set_array(&itemptr, "mouse", mousef); + RNA_float_set(&itemptr, "pressure", p->pressure); - /* handle drawing/erasing -> test for erasing first */ - if (p->paintmode == GP_PAINTMODE_ERASER) { - /* do 'live' erasing now */ - gp_stroke_doeraser(p); - - /* store used values */ - p->mvalo[0]= p->mval[0]; - p->mvalo[1]= p->mval[1]; - p->opressure= p->pressure; + /* apply the current latest drawing point */ + gpencil_draw_apply(C, op, p); + + /* force refresh */ + WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL); // XXX please work! +} + +/* ------------------------------- */ + +/* operator 'redo' (i.e. after changing some properties) */ +static int gpencil_draw_exec (bContext *C, wmOperator *op) +{ + tGPsdata *p = NULL; + + printf("GPencil - Starting Re-Drawing \n"); + + /* try to initialise context data needed while drawing */ + if (!gpencil_draw_init(C, op)) { + if (op->customdata) MEM_freeN(op->customdata); + printf("\tGP - no valid data \n"); + return OPERATOR_CANCELLED; } - /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ - else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { - /* try to add point */ - short ok= gp_stroke_addpoint(p, p->mval, p->pressure); + else + p= op->customdata; + + printf("\tGP - Start redrawing stroke \n"); + + /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement), + * setting the relevant values in context at each step, then applying + */ + RNA_BEGIN(op->ptr, itemptr, "stroke") + { + float mousef[2]; - /* handle errors while adding point */ - if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { - /* finish off old stroke */ - gp_paint_strokeend(p); - - /* start a new stroke, starting from previous point */ - gp_stroke_addpoint(p, p->mvalo, p->opressure); - ok= gp_stroke_addpoint(p, p->mval, p->pressure); - } - else if (ok == GP_STROKEADD_INVALID) { - /* the painting operation cannot continue... */ - BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke"); - p->status = GP_STATUS_ERROR; + printf("\t\tGP - stroke elem \n"); + + /* get relevant data for this point from stroke */ + RNA_float_get_array(&itemptr, "mouse", mousef); + p->mval[0] = (short)mousef[0]; + p->mval[1] = (short)mousef[1]; + p->pressure= RNA_float_get(&itemptr, "pressure"); + + /* if first run, set previous data too */ + if (p->flags & GP_PAINTFLAG_FIRSTRUN) { + p->flags &= ~GP_PAINTFLAG_FIRSTRUN; - if (G.f & G_DEBUG) - printf("Error: Grease-Pencil Paint - Add Point Invalid \n"); - // XXX break! + p->mvalo[0]= p->mval[0]; + p->mvalo[1]= p->mval[1]; + p->opressure= p->pressure; } - /* store used values */ - p->mvalo[0]= p->mval[0]; - p->mvalo[1]= p->mval[1]; - p->opressure= p->pressure; + /* apply this data as necessary now (as per usual) */ + gpencil_draw_apply(C, op, p); } + RNA_END; - /* force refresh */ - WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL); // XXX please work! + printf("\tGP - done \n"); + + /* cleanup */ + gpencil_draw_exit(C, op); + + /* done */ + return OPERATOR_FINISHED; } /* ------------------------------- */ +/* start of interactive drawing part of operator */ static int gpencil_draw_invoke (bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p = NULL; + wmWindow *win= CTX_wm_window(C); printf("GPencil - Starting Drawing \n"); @@ -1177,16 +1262,35 @@ static int gpencil_draw_invoke (bContext *C, wmOperator *op, wmEvent *event) // TODO: this involves mucking around with radial control, so we leave this for now.. } - printf("\tGP - set first spot\n"); + /* set cursor */ + if (p->paintmode == GP_PAINTMODE_ERASER) + WM_cursor_modal(win, BC_CROSSCURSOR); // XXX need a better cursor + else + WM_cursor_modal(win, BC_PAINTBRUSHCURSOR); - /* handle the initial drawing - i.e. for just doing a simple dot */ - gpencil_draw_apply_event(C, op, event); + /* special hack: if there was an initial event, then we were invoked via a hotkey, and + * 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) { + /* hotkey invoked - start drawing */ + printf("\tGP - set first spot\n"); + p->status= GP_STATUS_PAINTING; + + /* handle the initial drawing - i.e. for just doing a simple dot */ + gpencil_draw_apply_event(C, op, event); + } + else { + /* toolbar invoked - don't start drawing yet... */ + printf("\tGP - hotkey invoked... waiting for click-drag\n"); + } /* add a modal handler for this operator, so that we can then draw continuous strokes */ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); return OPERATOR_RUNNING_MODAL; } +/* events handling during interactive drawing part of operator */ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p= op->customdata; @@ -1198,25 +1302,35 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event) * otherwise, carry on to mouse-move... */ case LEFTMOUSE: - case MIDDLEMOUSE: case RIGHTMOUSE: - if (event->val != KM_PRESS) { + /* if painting, end stroke */ + if (p->status == GP_STATUS_PAINTING) { + /* basically, this should be mouse-button up */ printf("\t\tGP - end of stroke \n"); gpencil_draw_exit(C, op); return OPERATOR_FINISHED; } + else { + /* not painting, so start stroke (this should be mouse-button down) */ + printf("\t\tGP - start stroke \n"); + p->status= GP_STATUS_PAINTING; + /* no break now, since we should immediately start painting */ + } - /* moving mouse - assumed that mouse button is down */ + /* moving mouse - assumed that mouse button is down if in painting status */ case MOUSEMOVE: - /* handle drawing event */ - printf("\t\tGP - add point\n"); - gpencil_draw_apply_event(C, op, event); - - /* finish painting operation if anything went wrong just now */ - if (p->status == GP_STATUS_ERROR) { - printf("\t\t\tGP - error done! \n"); - gpencil_draw_exit(C, op); - return OPERATOR_CANCELLED; + /* check if we're currently painting */ + if (p->status == GP_STATUS_PAINTING) { + /* handle drawing event */ + printf("\t\tGP - add point\n"); + gpencil_draw_apply_event(C, op, event); + + /* finish painting operation if anything went wrong just now */ + if (p->status == GP_STATUS_ERROR) { + printf("\t\t\tGP - error done! \n"); + gpencil_draw_exit(C, op); + return OPERATOR_CANCELLED; + } } break; @@ -1229,17 +1343,7 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event) case WHEELDOWNMOUSE: p->radius -= 1.5f; break; - - /* handle ctrl key - used to toggle straight-lines only (for drawing) */ - // XXX hardcoded keymap stuff - case LEFTCTRLKEY: - case RIGHTCTRLKEY: - if (event->val == KM_PRESS) - p->flags |= GP_PAINTFLAG_STRAIGHTLINES; - else if (event->val == KM_RELEASE) - p->flags &= ~GP_PAINTFLAG_STRAIGHTLINES; - break; - + default: printf("\t\tGP unknown event - %d \n", event->type); break; @@ -1264,7 +1368,7 @@ void GPENCIL_OT_draw (wmOperatorType *ot) ot->description= "Make annotations on the active data."; /* api callbacks */ - //ot->exec= gpencil_draw_exec; + ot->exec= gpencil_draw_exec; ot->invoke= gpencil_draw_invoke; ot->modal= gpencil_draw_modal; ot->cancel= gpencil_draw_cancel; @@ -1275,4 +1379,7 @@ void GPENCIL_OT_draw (wmOperatorType *ot) /* settings for drawing */ RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to intepret mouse movements."); + RNA_def_boolean(ot->srna, "straight_lines", 0, "Straight Lines", "Only take the endpoints of the strokes, so that straight lines can be drawn."); + + RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); } |