diff options
author | Joshua Leung <aligorith@gmail.com> | 2008-08-27 17:02:44 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2008-08-27 17:02:44 +0400 |
commit | c6acbc30474bbe1b0f67642b93e188c3eccdb92b (patch) | |
tree | d4b09ca723c25b28c2c391a7b793cb6a95075be2 /source | |
parent | 6cccdf0cb2602b46e9c1e0a0a7f40853626735cf (diff) |
== Grease Pencil - Conversions + Bugfixes ==
* New stuff: Grease Pencil strokes on the active layer can now be converted to 3d curves (geometry). More work is still needed to make the result look be more optimal (i.e. extruded curve)
* Bugfix: Spacing between collapsed layers is more compact now
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/include/BDR_gpencil.h | 3 | ||||
-rw-r--r-- | source/blender/include/BSE_drawipo.h | 3 | ||||
-rw-r--r-- | source/blender/src/drawgpencil.c | 2 | ||||
-rw-r--r-- | source/blender/src/drawipo.c | 2 | ||||
-rw-r--r-- | source/blender/src/editobject.c | 6 | ||||
-rw-r--r-- | source/blender/src/gpencil.c | 168 |
6 files changed, 173 insertions, 11 deletions
diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h index 7340a2e44e0..9b9294b0343 100644 --- a/source/blender/include/BDR_gpencil.h +++ b/source/blender/include/BDR_gpencil.h @@ -76,6 +76,9 @@ void gpencil_delete_laststroke(struct bGPdata *gpd); void gpencil_delete_operation(short mode); void gpencil_delete_menu(void); +void gpencil_convert_operation(short mode); +void gpencil_convert_menu(void); + //short gpencil_paint(short mousebutton); short gpencil_do_paint(struct ScrArea *sa, short mousebutton); diff --git a/source/blender/include/BSE_drawipo.h b/source/blender/include/BSE_drawipo.h index 932f103a579..b8388b2172a 100644 --- a/source/blender/include/BSE_drawipo.h +++ b/source/blender/include/BSE_drawipo.h @@ -42,6 +42,7 @@ struct ScrArea; struct EditIpo; struct View2D; struct rctf; +struct SpaceLink; void calc_ipogrid(void); void draw_ipogrid(void); @@ -50,6 +51,8 @@ void areamouseco_to_ipoco (struct View2D *v2d, short *mval, float *x, float *y); void ipoco_to_areaco (struct View2D *v2d, float *vec, short *mval); void ipoco_to_areaco_noclip (struct View2D *v2d, float *vec, short *mval); +struct View2D *spacelink_get_view2d(struct SpaceLink *sl); + void view2d_do_locks (struct ScrArea *cursa, int flag); void view2d_zoom (struct View2D *v2d, float factor, int winx, int winy); void view2d_getscale (struct View2D *v2d, float *x, float *y); diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index dc9a880086f..4b6b5ab26c8 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -177,7 +177,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) { char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */ - height= 26; + height= 0; /* visibility button (only if hidden but not locked!) */ if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED)) diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 71854570c8c..9b5be04eac1 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -442,7 +442,7 @@ int in_ipo_buttons(void) else return 1; } -static View2D *spacelink_get_view2d(SpaceLink *sl) +View2D *spacelink_get_view2d(SpaceLink *sl) { if(sl->spacetype==SPACE_IPO) return &((SpaceIpo *)sl)->v2d; diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index fee967bcd9a..b1205668faa 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -172,6 +172,7 @@ #include "BDR_drawobject.h" #include "BDR_editcurve.h" #include "BDR_unwrapper.h" +#include "BDR_gpencil.h" #include <time.h> #include "mydevice.h" @@ -2827,7 +2828,10 @@ void convertmenu(void) if(G.scene->id.lib) return; obact= OBACT; - if(obact==0) return; + if(obact==0) { + gpencil_convert_menu(); + return; + } if(!obact->flag & SELECT) return; if(G.obedit) return; diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index 0b28e778f62..d1599d765b5 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -46,7 +46,9 @@ #include "BLI_blenlib.h" #include "DNA_listBase.h" +#include "DNA_curve_types.h" #include "DNA_gpencil_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -57,6 +59,7 @@ #include "BKE_global.h" #include "BKE_utildefines.h" #include "BKE_blender.h" +#include "BKE_curve.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -74,6 +77,8 @@ #include "BDR_gpencil.h" #include "BIF_drawgpencil.h" +#include "BDR_editobject.h" + #include "BSE_drawipo.h" #include "BSE_headerbuttons.h" #include "BSE_view.h" @@ -678,6 +683,152 @@ void gpencil_delete_menu (void) gpencil_delete_operation(mode); } +/* --------- Data Conversion ---------- */ + +/* convert the coordinates from the given stroke point into 3d-coordinates */ +static void gp_strokepoint_convertcoords (bGPDstroke *gps, bGPDspoint *pt, float p3d[3]) +{ + if (gps->flag & GP_STROKE_3DSPACE) { + /* directly use 3d-coordinates */ + // FIXME: maybe we need to counterotate this for object rotation? + VecCopyf(p3d, &pt->x); + } + else { + short mval[2], mx, my; + float *fp= give_cursor(); + float dvec[3]; + + /* get screen coordinate */ + if (gps->flag & GP_STROKE_2DSPACE) { + View2D *v2d= spacelink_get_view2d(curarea->spacedata.first); + ipoco_to_areaco_noclip(v2d, &pt->x, mval); + } + else { + mval[0]= (pt->x / 1000 * curarea->winx); + mval[1]= (pt->y / 1000 * curarea->winy); + } + mx= mval[0]; + my= mval[1]; + + /* convert screen coordinate to 3d coordinates + * - method taken from editview.c - mouse_cursor() + */ + project_short_noclip(fp, mval); + window_to_3d(dvec, mval[0]-mx, mval[1]-my); + VecSubf(p3d, fp, dvec); + } +} + +/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ +static void gp_layer_to_curve (bGPdata *gpd, bGPDlayer *gpl) +{ + bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps; + Object *ob; + Curve *cu; + float *fp= give_cursor(); + char name[140]; + + /* error checking */ + if (ELEM3(NULL, gpd, gpl, gpf)) + return; + + /* only convert if there are any strokes on this layer's frame to convert */ + if (gpf->strokes.first == NULL) + return; + + /* initialise the curve */ + sprintf(name, "GP_%s", gpl->info); + cu= add_curve(name, 1); + cu->flag |= CU_3D; + + /* init the curve object (remove rotation and assign curve data to it) */ + add_object_draw(OB_CURVE); + ob= OBACT; + ob->rot[0]= ob->rot[1]= ob->rot[2]= 0; + ob->data= cu; + + /* initialise 3d-cursor correction globals */ + initgrabz(fp[0], fp[1], fp[2]); + + /* add points to curve */ + for (gps= gpf->strokes.first; gps; gps= gps->next) { + bGPDspoint *pt; + Nurb *nu; + BPoint *bp; + int i; + + /* create new 'nurb' within the curve */ + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_curve(nurb)"); + + nu->pntsu= gps->totpoints; + nu->pntsv= 1; + nu->orderu= gps->totpoints; + nu->flagu= 2; /* endpoint */ + nu->resolu= 32; + + nu->bp= MEM_callocN(sizeof(BPoint)*gps->totpoints, "bezts"); + + /* add points */ + for (i=0, pt=gps->points, bp=nu->bp; i < gps->totpoints; i++, pt++, bp++) { + float p3d[3]; + + /* get coordinates to add at */ + gp_strokepoint_convertcoords(gps, pt, p3d); + VecCopyf(bp->vec, p3d); + + /* set settings */ + bp->f1= SELECT; + bp->radius = bp->weight = pt->pressure * gpl->thickness; + } + + /* add nurb to curve */ + BLI_addtail(&cu->nurb, nu); + } +} + +/* convert grease-pencil strokes to another representation + * mode: 1 - Active layer to curve + */ +void gpencil_convert_operation (short mode) +{ + bGPdata *gpd; + + /* get datablock to work on */ + gpd= gpencil_data_getactive(NULL); + if (gpd == NULL) return; + + /* handle selection modes */ + switch (mode) { + case 1: /* active layer only */ + { + bGPDlayer *gpl= gpencil_layer_getactive(gpd); + gp_layer_to_curve(gpd, gpl); + } + break; + } + + /* redraw and undo-push */ + BIF_undo_push("GPencil Convert"); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWOOPS, 0); +} + +/* display a menu for converting grease-pencil strokes */ +void gpencil_convert_menu (void) +{ + bGPdata *gpd= gpencil_data_getactive(NULL); + short mode; + + /* only show menu if it will be relevant */ + if (gpd == NULL) return; + + mode= pupmenu("Grease Pencil Convert %t|Active Layer To Curve%x1"); + if (mode <= 0) return; + + gpencil_convert_operation(mode); +} + /* ************************************************** */ /* GREASE-PENCIL EDITING MODE - Painting */ @@ -1113,12 +1264,11 @@ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i) /* eraser tool - check if part of stroke occurs within last segment drawn by eraser */ static short gp_stroke_eraser_strokeinside (short mval[], short mvalo[], short rad, short x0, short y0, short x1, short y1) { - /* step 1: check if within the radius for the new one */ - /* simple within-radius check */ + /* simple within-radius check for now */ if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1)) return 1; - /* step 2: check if within the quad formed between the two eraser coords */ + /* not inside */ return 0; } @@ -1203,7 +1353,6 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], /* 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 - * - handled using the lasso-select checking code */ 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) */ @@ -1288,6 +1437,12 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode) case SPACE_SEQ: { /* for now, this is not applicable here... */ + //p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE; + } + break; + case SPACE_IMAGE: + { + p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE; } break; } @@ -1298,10 +1453,7 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode) static void gp_paint_strokeend (tGPsdata *p) { /* check if doing eraser or not */ - if (p->gpd->sbuffer_sflag & GP_STROKE_ERASER) { - /* don't do anything */ - } - else { + if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* transfer stroke to frame */ gp_stroke_newfrombuffer(p); } |