Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/src/gpencil.c')
-rw-r--r--source/blender/src/gpencil.c224
1 files changed, 216 insertions, 8 deletions
diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c
index 0b28e778f62..0148ace20d4 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,208 @@ 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 stroke to 3d path */
+static void gp_layer_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
+{
+ bGPDspoint *pt;
+ Nurb *nu;
+ BPoint *bp;
+ int i;
+
+ /* create new 'nurb' within the curve */
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
+
+ nu->pntsu= gps->totpoints;
+ nu->pntsv= 1;
+ nu->orderu= gps->totpoints;
+ nu->flagu= 2; /* endpoint */
+ nu->resolu= 32;
+
+ nu->bp= (BPoint *)MEM_callocN(sizeof(BPoint)*gps->totpoints, "bpoints");
+
+ /* 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 stroke to 3d bezier */
+static void gp_layer_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
+{
+ bGPDspoint *pt;
+ Nurb *nu;
+ BezTriple *bezt;
+ int i;
+
+ /* create new 'nurb' within the curve */
+ nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
+
+ nu->pntsu= gps->totpoints;
+ nu->resolu= 12;
+ nu->resolv= 12;
+ nu->type= CU_BEZIER;
+ nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints*sizeof(BezTriple), "bezts");
+
+ /* add points */
+ for (i=0, pt=gps->points, bezt=nu->bezt; i < gps->totpoints; i++, pt++, bezt++) {
+ float p3d[3];
+
+ /* get coordinates to add at */
+ gp_strokepoint_convertcoords(gps, pt, p3d);
+
+ /* TODO: maybe in future the handles shouldn't be in same place */
+ VecCopyf(bezt->vec[0], p3d);
+ VecCopyf(bezt->vec[1], p3d);
+ VecCopyf(bezt->vec[2], p3d);
+
+ /* set settings */
+ bezt->h1= bezt->h2= HD_FREE;
+ bezt->f1= bezt->f2= bezt->f3= SELECT;
+ bezt->radius = bezt->weight = pt->pressure * gpl->thickness;
+ }
+
+ /* must calculate handles or else we crash */
+ calchandlesNurb(nu);
+
+ /* add nurb to curve */
+ BLI_addtail(&cu->nurb, nu);
+}
+
+/* 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, short mode)
+{
+ bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+ bGPDstroke *gps;
+ Object *ob;
+ Curve *cu;
+
+ /* 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 */
+ cu= add_curve(gpl->info, 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->loc[0]= ob->loc[1]= ob->loc[2]= 0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0;
+ ob->data= cu;
+
+ /* add points to curve */
+ for (gps= gpf->strokes.first; gps; gps= gps->next) {
+ switch (mode) {
+ case 1:
+ gp_layer_to_path(gpl, gps, cu);
+ break;
+ case 2:
+ gp_layer_to_bezier(gpl, gps, cu);
+ break;
+ }
+ }
+}
+
+/* convert grease-pencil strokes to another representation
+ * mode: 1 - Active layer to path
+ * 2 - Active layer to bezier
+ */
+void gpencil_convert_operation (short mode)
+{
+ bGPdata *gpd;
+ float *fp= give_cursor();
+
+ /* get datablock to work on */
+ gpd= gpencil_data_getactive(NULL);
+ if (gpd == NULL) return;
+
+ /* initialise 3d-cursor correction globals */
+ initgrabz(fp[0], fp[1], fp[2]);
+
+ /* handle selection modes */
+ switch (mode) {
+ case 1: /* active layer only (to path) */
+ case 2: /* active layer only (to bezier) */
+ {
+ bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+ gp_layer_to_curve(gpd, gpl, mode);
+ }
+ 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 Path%x1|Active Layer to Bezier%x2");
+ if (mode <= 0) return;
+
+ gpencil_convert_operation(mode);
+}
+
/* ************************************************** */
/* GREASE-PENCIL EDITING MODE - Painting */
@@ -1113,12 +1320,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 +1409,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 +1493,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 +1509,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);
}