== 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
This commit is contained in:
2008-08-27 13:02:44 +00:00
parent 6cccdf0cb2
commit c6acbc3047
6 changed files with 173 additions and 11 deletions

View File

@@ -76,6 +76,9 @@ void gpencil_delete_laststroke(struct bGPdata *gpd);
void gpencil_delete_operation(short mode); void gpencil_delete_operation(short mode);
void gpencil_delete_menu(void); void gpencil_delete_menu(void);
void gpencil_convert_operation(short mode);
void gpencil_convert_menu(void);
//short gpencil_paint(short mousebutton); //short gpencil_paint(short mousebutton);
short gpencil_do_paint(struct ScrArea *sa, short mousebutton); short gpencil_do_paint(struct ScrArea *sa, short mousebutton);

View File

@@ -42,6 +42,7 @@ struct ScrArea;
struct EditIpo; struct EditIpo;
struct View2D; struct View2D;
struct rctf; struct rctf;
struct SpaceLink;
void calc_ipogrid(void); void calc_ipogrid(void);
void draw_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 (struct View2D *v2d, float *vec, short *mval);
void ipoco_to_areaco_noclip (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_do_locks (struct ScrArea *cursa, int flag);
void view2d_zoom (struct View2D *v2d, float factor, int winx, int winy); void view2d_zoom (struct View2D *v2d, float factor, int winx, int winy);
void view2d_getscale (struct View2D *v2d, float *x, float *y); void view2d_getscale (struct View2D *v2d, float *x, float *y);

View File

@@ -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)) { 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 */ 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!) */ /* visibility button (only if hidden but not locked!) */
if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED)) if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))

View File

@@ -442,7 +442,7 @@ int in_ipo_buttons(void)
else return 1; else return 1;
} }
static View2D *spacelink_get_view2d(SpaceLink *sl) View2D *spacelink_get_view2d(SpaceLink *sl)
{ {
if(sl->spacetype==SPACE_IPO) if(sl->spacetype==SPACE_IPO)
return &((SpaceIpo *)sl)->v2d; return &((SpaceIpo *)sl)->v2d;

View File

@@ -172,6 +172,7 @@
#include "BDR_drawobject.h" #include "BDR_drawobject.h"
#include "BDR_editcurve.h" #include "BDR_editcurve.h"
#include "BDR_unwrapper.h" #include "BDR_unwrapper.h"
#include "BDR_gpencil.h"
#include <time.h> #include <time.h>
#include "mydevice.h" #include "mydevice.h"
@@ -2827,7 +2828,10 @@ void convertmenu(void)
if(G.scene->id.lib) return; if(G.scene->id.lib) return;
obact= OBACT; obact= OBACT;
if(obact==0) return; if(obact==0) {
gpencil_convert_menu();
return;
}
if(!obact->flag & SELECT) return; if(!obact->flag & SELECT) return;
if(G.obedit) return; if(G.obedit) return;

View File

@@ -46,7 +46,9 @@
#include "BLI_blenlib.h" #include "BLI_blenlib.h"
#include "DNA_listBase.h" #include "DNA_listBase.h"
#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h" #include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "DNA_screen_types.h" #include "DNA_screen_types.h"
#include "DNA_space_types.h" #include "DNA_space_types.h"
@@ -57,6 +59,7 @@
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_utildefines.h" #include "BKE_utildefines.h"
#include "BKE_blender.h" #include "BKE_blender.h"
#include "BKE_curve.h"
#include "BIF_gl.h" #include "BIF_gl.h"
#include "BIF_glutil.h" #include "BIF_glutil.h"
@@ -74,6 +77,8 @@
#include "BDR_gpencil.h" #include "BDR_gpencil.h"
#include "BIF_drawgpencil.h" #include "BIF_drawgpencil.h"
#include "BDR_editobject.h"
#include "BSE_drawipo.h" #include "BSE_drawipo.h"
#include "BSE_headerbuttons.h" #include "BSE_headerbuttons.h"
#include "BSE_view.h" #include "BSE_view.h"
@@ -678,6 +683,152 @@ void gpencil_delete_menu (void)
gpencil_delete_operation(mode); 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 */ /* 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 */ /* 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) 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 for now */
/* simple within-radius check */
if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1)) if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1))
return 1; return 1;
/* step 2: check if within the quad formed between the two eraser coords */ /* not inside */
return 0; 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 /* check if point segment of stroke had anything to do with
* eraser region (either within stroke painted, or on its lines) * eraser region (either within stroke painted, or on its lines)
* - this assumes that linewidth is irrelevant * - 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 (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 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: case SPACE_SEQ:
{ {
/* for now, this is not applicable here... */ /* 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; break;
} }
@@ -1298,10 +1453,7 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode)
static void gp_paint_strokeend (tGPsdata *p) static void gp_paint_strokeend (tGPsdata *p)
{ {
/* check if doing eraser or not */ /* check if doing eraser or not */
if (p->gpd->sbuffer_sflag & GP_STROKE_ERASER) { if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
/* don't do anything */
}
else {
/* transfer stroke to frame */ /* transfer stroke to frame */
gp_stroke_newfrombuffer(p); gp_stroke_newfrombuffer(p);
} }