Grease Pencil - Stick to View for Sequencer:
[blender.git] / source / blender / src / gpencil.c
1 /**
2  * $Id: gpencil.c 14881 2008-05-18 10:41:42Z aligorith $
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008, Blender Foundation
21  * This is a new part of Blender
22  *
23  * Contributor(s): Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27  
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stddef.h>
32 #include <math.h>
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BMF_Api.h"
41
42 #include "IMB_imbuf.h"
43 #include "IMB_imbuf_types.h"
44
45 #include "BLI_arithb.h"
46 #include "BLI_blenlib.h"
47
48 #include "DNA_listBase.h"
49 #include "DNA_armature_types.h"
50 #include "DNA_curve_types.h"
51 #include "DNA_gpencil_types.h"
52 #include "DNA_object_types.h"
53 #include "DNA_scene_types.h"
54 #include "DNA_screen_types.h"
55 #include "DNA_space_types.h"
56 #include "DNA_userdef_types.h"
57 #include "DNA_vec_types.h"
58 #include "DNA_view3d_types.h"
59
60 #include "BKE_global.h"
61 #include "BKE_utildefines.h"
62 #include "BKE_blender.h"
63 #include "BKE_armature.h"
64 #include "BKE_curve.h"
65 #include "BKE_image.h"
66
67 #include "BIF_gl.h"
68 #include "BIF_glutil.h"
69 #include "BIF_butspace.h"
70 #include "BIF_drawseq.h"
71 #include "BIF_editarmature.h"
72 #include "BIF_editview.h"
73 #include "BIF_graphics.h"
74 #include "BIF_interface.h"
75 #include "BIF_mywindow.h"
76 #include "BIF_resources.h"
77 #include "BIF_space.h"
78 #include "BIF_screen.h"
79 #include "BIF_toolbox.h"
80 #include "BIF_toets.h"
81
82 #include "BDR_gpencil.h"
83 #include "BIF_drawgpencil.h"
84
85 #include "BDR_editobject.h"
86
87 #include "BSE_drawipo.h"
88 #include "BSE_headerbuttons.h"
89 #include "BSE_view.h"
90
91 #include "blendef.h"
92
93 #include "PIL_time.h"                   /* sleep                                */
94 #include "mydevice.h"
95
96 /* ************************************************** */
97 /* GENERAL STUFF */
98
99 /* --------- Memory Management ------------ */
100
101 /* Free strokes belonging to a gp-frame */
102 void free_gpencil_strokes (bGPDframe *gpf)
103 {
104         bGPDstroke *gps, *gpsn;
105         
106         /* error checking */
107         if (gpf == NULL) return;
108         
109         /* free strokes */
110         for (gps= gpf->strokes.first; gps; gps= gpsn) {
111                 gpsn= gps->next;
112                 
113                 /* free stroke memory arrays, then stroke itself */
114                 MEM_freeN(gps->points);
115                 BLI_freelinkN(&gpf->strokes, gps);
116         }
117 }
118
119 /* Free all of a gp-layer's frames */
120 void free_gpencil_frames (bGPDlayer *gpl)
121 {
122         bGPDframe *gpf, *gpfn;
123         
124         /* error checking */
125         if (gpl == NULL) return;
126         
127         /* free frames */
128         for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
129                 gpfn= gpf->next;
130                 
131                 /* free strokes and their associated memory */
132                 free_gpencil_strokes(gpf);
133                 BLI_freelinkN(&gpl->frames, gpf);
134         }
135 }
136
137 /* Free all of the gp-layers for a viewport (list should be &G.vd->gpd or so) */
138 void free_gpencil_layers (ListBase *list) 
139 {
140         bGPDlayer *gpl, *gpln;
141         
142         /* error checking */
143         if (list == NULL) return;
144         
145         /* delete layers*/
146         for (gpl= list->first; gpl; gpl= gpln) {
147                 gpln= gpl->next;
148                 
149                 /* free layers and their data */
150                 free_gpencil_frames(gpl);
151                 BLI_freelinkN(list, gpl);
152         }
153 }
154
155 /* Free gp-data and all it's related data */
156 void free_gpencil_data (bGPdata *gpd)
157 {
158         /* free layers then data itself */
159         free_gpencil_layers(&gpd->layers);
160         MEM_freeN(gpd);
161 }
162
163 /* -------- Container Creation ---------- */
164
165 /* add a new gp-frame to the given layer */
166 bGPDframe *gpencil_frame_addnew (bGPDlayer *gpl, int cframe)
167 {
168         bGPDframe *gpf, *gf;
169         short state=0;
170         
171         /* error checking */
172         if ((gpl == NULL) || (cframe <= 0))
173                 return NULL;
174                 
175         /* allocate memory for this frame */
176         gpf= MEM_callocN(sizeof(bGPDframe), "bGPDframe");
177         gpf->framenum= cframe;
178         
179         /* find appropriate place to add frame */
180         if (gpl->frames.first) {
181                 for (gf= gpl->frames.first; gf; gf= gf->next) {
182                         /* check if frame matches one that is supposed to be added */
183                         if (gf->framenum == cframe) {
184                                 state= -1;
185                                 break;
186                         }
187                         
188                         /* if current frame has already exceeded the frame to add, add before */
189                         if (gf->framenum > cframe) {
190                                 BLI_insertlinkbefore(&gpl->frames, gf, gpf);
191                                 state= 1;
192                                 break;
193                         }
194                 }
195         }
196         
197         /* check whether frame was added successfully */
198         if (state == -1) {
199                 MEM_freeN(gpf);
200                 printf("Error: frame (%d) existed already for this layer \n", cframe);
201         }
202         else if (state == 0) {
203                 /* add to end then! */
204                 BLI_addtail(&gpl->frames, gpf);
205         }
206         
207         /* return frame */
208         return gpf;
209 }
210
211 /* add a new gp-layer and make it the active layer */
212 bGPDlayer *gpencil_layer_addnew (bGPdata *gpd)
213 {
214         bGPDlayer *gpl;
215         
216         /* check that list is ok */
217         if (gpd == NULL)
218                 return NULL;
219                 
220         /* allocate memory for frame and add to end of list */
221         gpl= MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
222         
223         /* add to datablock */
224         BLI_addtail(&gpd->layers, gpl);
225         
226         /* set basic settings */
227         gpl->color[3]= 1.0f;
228         gpl->thickness = 1;
229         
230         /* auto-name */
231         sprintf(gpl->info, "GP_Layer");
232         BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info[0]), 128);
233         
234         /* make this one the active one */
235         gpencil_layer_setactive(gpd, gpl);
236         
237         /* return layer */
238         return gpl;
239 }
240
241 /* add a new gp-datablock */
242 bGPdata *gpencil_data_addnew (void)
243 {
244         bGPdata *gpd;
245         
246         /* allocate memory for a new block */
247         gpd= MEM_callocN(sizeof(bGPdata), "GreasePencilData");
248         
249         /* initial settings */
250                 /* it is quite useful to be able to see this info, so on by default */
251         gpd->flag = GP_DATA_DISPINFO;
252         
253         return gpd;
254 }
255
256 /* -------- Data Duplication ---------- */
257
258 /* make a copy of a given gpencil datablock */
259 bGPdata *gpencil_data_duplicate (bGPdata *src)
260 {
261         bGPdata *dst;
262         bGPDlayer *gpld, *gpls;
263         bGPDframe *gpfd, *gpfs;
264         bGPDstroke *gps;
265         
266         /* error checking */
267         if (src == NULL)
268                 return NULL;
269         
270         /* make a copy of the base-data */
271         dst= MEM_dupallocN(src);
272         
273         /* copy layers */
274         duplicatelist(&dst->layers, &src->layers);
275         
276         for (gpld=dst->layers.first, gpls=src->layers.first; gpld && gpls; 
277                  gpld=gpld->next, gpls=gpls->next) 
278         {
279                 /* copy frames */
280                 duplicatelist(&gpld->frames, &gpls->frames);
281                 
282                 for (gpfd=gpld->frames.first, gpfs=gpls->frames.first; gpfd && gpfs;
283                          gpfd=gpfd->next, gpfs=gpfs->next) 
284                 {
285                         /* copy strokes */
286                         duplicatelist(&gpfd->strokes, &gpfs->strokes);
287                         
288                         for (gps= gpfd->strokes.first; gps; gps= gps->next) 
289                         {
290                                 gps->points= MEM_dupallocN(gps->points);
291                         }
292                 }
293         }
294         
295         /* return new */
296         return dst;
297 }
298
299 /* ----------- GP-Datablock API ------------- */
300
301 /* get the appropriate bGPdata from the active/given context */
302 bGPdata *gpencil_data_getactive (ScrArea *sa)
303 {
304         /* error checking */
305         if ((sa == NULL) && (curarea == NULL))
306                 return NULL;
307         if (sa == NULL)
308                 sa= curarea;
309                 
310         /* handle depending on spacetype */
311         switch (sa->spacetype) {
312                 case SPACE_VIEW3D:
313                 {
314                         View3D *v3d= sa->spacedata.first;
315                         return v3d->gpd;
316                 }
317                         break;
318                 case SPACE_NODE:
319                 {
320                         SpaceNode *snode= sa->spacedata.first;
321                         return snode->gpd;
322                 }
323                         break;
324                 case SPACE_SEQ:
325                 {
326                         SpaceSeq *sseq= sa->spacedata.first;
327                         
328                         /* only applicable for image modes */
329                         if (sseq->mainb)
330                                 return sseq->gpd;
331                 }
332                         break;
333                 case SPACE_IMAGE:
334                 {
335                         SpaceImage *sima= sa->spacedata.first;
336                         return sima->gpd;
337                 }
338                         break;
339         }
340         
341         /* nothing found */
342         return NULL;
343 }
344
345 /* set bGPdata for the active/given context, and return success/fail */
346 short gpencil_data_setactive (ScrArea *sa, bGPdata *gpd)
347 {
348         /* error checking */
349         if ((sa == NULL) && (curarea == NULL))
350                 return 0;
351         if (gpd == NULL)
352                 return 0;
353         if (sa == NULL)
354                 sa= curarea;
355         
356         /* handle depending on spacetype */
357         // TODO: someday we should have multi-user data, so no need to loose old data
358         switch (sa->spacetype) {
359                 case SPACE_VIEW3D:
360                 {
361                         View3D *v3d= sa->spacedata.first;
362                         
363                         /* free the existing block */
364                         if (v3d->gpd)
365                                 free_gpencil_data(v3d->gpd);
366                         v3d->gpd= gpd;
367                         
368                         return 1;
369                 }
370                         break;
371                 case SPACE_NODE:
372                 {
373                         SpaceNode *snode= sa->spacedata.first;
374                         
375                         /* free the existing block */
376                         if (snode->gpd)
377                                 free_gpencil_data(snode->gpd);
378                         snode->gpd= gpd;
379                         
380                         /* set special settings */
381                         gpd->flag |= GP_DATA_VIEWALIGN;
382                         
383                         return 1;
384                 }
385                         break;
386                 case SPACE_SEQ:
387                 {
388                         SpaceSeq *sseq= sa->spacedata.first;
389                         
390                         /* only applicable if right mode */
391                         if (sseq->mainb) {
392                                 /* free the existing block */
393                                 if (sseq->gpd)
394                                         free_gpencil_data(sseq->gpd);
395                                 sseq->gpd= gpd;
396                                 
397                                 return 1;
398                         }
399                 }
400                         break;
401                 case SPACE_IMAGE:
402                 {
403                         SpaceImage *sima= sa->spacedata.first;
404                         
405                         if (sima->gpd)
406                                 free_gpencil_data(sima->gpd);
407                         sima->gpd= gpd;
408                         
409                         return 1;
410                 }
411                         break;
412         }
413         
414         /* failed to add */
415         return 0;
416 }
417
418 /* -------- GP-Frame API ---------- */
419
420 /* delete the last stroke of the given frame */
421 void gpencil_frame_delete_laststroke (bGPDframe *gpf)
422 {
423         bGPDstroke *gps= (gpf) ? gpf->strokes.last : NULL;
424         
425         /* error checking */
426         if (ELEM(NULL, gpf, gps))
427                 return;
428         
429         /* free the stroke and its data */
430         MEM_freeN(gps->points);
431         BLI_freelinkN(&gpf->strokes, gps);
432 }
433
434 /* -------- GP-Layer API ---------- */
435
436 /* get the appropriate gp-frame from a given layer
437  *      - this sets the layer's actframe var (if allowed to)
438  *      - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
439  */
440 bGPDframe *gpencil_layer_getframe (bGPDlayer *gpl, int cframe, short addnew)
441 {
442         bGPDframe *gpf = NULL;
443         short found = 0;
444         
445         /* error checking */
446         if (gpl == NULL) return NULL;
447         if (cframe <= 0) cframe = 1;
448         
449         /* check if there is already an active frame */
450         if (gpl->actframe) {
451                 gpf= gpl->actframe;
452                 
453                 /* do not allow any changes to layer's active frame if layer is locked */
454                 if (gpl->flag & GP_LAYER_LOCKED)
455                         return gpf;
456                 /* do not allow any changes to actframe if frame has painting tag attached to it */
457                 if (gpf->flag & GP_FRAME_PAINT) 
458                         return gpf;
459                 
460                 /* try to find matching frame */
461                 if (gpf->framenum < cframe) {
462                         for (; gpf; gpf= gpf->next) {
463                                 if (gpf->framenum == cframe) {
464                                         found= 1;
465                                         break;
466                                 }
467                                 else if ((gpf->next) && (gpf->next->framenum > cframe)) {
468                                         found= 1;
469                                         break;
470                                 }
471                         }
472                         
473                         /* set the appropriate frame */
474                         if (addnew) {
475                                 if ((found) && (gpf->framenum == cframe))
476                                         gpl->actframe= gpf;
477                                 else
478                                         gpl->actframe= gpencil_frame_addnew(gpl, cframe);
479                         }
480                         else if (found)
481                                 gpl->actframe= gpf;
482                         else
483                                 gpl->actframe= gpl->frames.last;
484                 }
485                 else {
486                         for (; gpf; gpf= gpf->prev) {
487                                 if (gpf->framenum <= cframe) {
488                                         found= 1;
489                                         break;
490                                 }
491                         }
492                         
493                         /* set the appropriate frame */
494                         if (addnew) {
495                                 if ((found) && (gpf->framenum == cframe))
496                                         gpl->actframe= gpf;
497                                 else
498                                         gpl->actframe= gpencil_frame_addnew(gpl, cframe);
499                         }
500                         else if (found)
501                                 gpl->actframe= gpf;
502                         else
503                                 gpl->actframe= gpl->frames.first;
504                 }
505         }
506         else if (gpl->frames.first) {
507                 /* check which of the ends to start checking from */
508                 const int first= ((bGPDframe *)(gpl->frames.first))->framenum;
509                 const int last= ((bGPDframe *)(gpl->frames.last))->framenum;
510                 
511                 if (abs(cframe-first) > abs(cframe-last)) {
512                         /* find gp-frame which is less than or equal to cframe */
513                         for (gpf= gpl->frames.last; gpf; gpf= gpf->prev) {
514                                 if (gpf->framenum <= cframe) {
515                                         found= 1;
516                                         break;
517                                 }
518                         }
519                 }
520                 else {
521                         /* find gp-frame which is less than or equal to cframe */
522                         for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
523                                 if (gpf->framenum <= cframe) {
524                                         found= 1;
525                                         break;
526                                 }
527                         }
528                 }
529                 
530                 /* set the appropriate frame */
531                 if (addnew) {
532                         if ((found) && (gpf->framenum == cframe))
533                                 gpl->actframe= gpf;
534                         else
535                                 gpl->actframe= gpencil_frame_addnew(gpl, cframe);
536                 }
537                 else if (found)
538                         gpl->actframe= gpf;
539                 else {
540                         /* unresolved errogenous situation! */
541                         printf("Error: cannot find appropriate gp-frame \n");
542                 }
543         }
544         else {
545                 /* currently no frames (add if allowed to) */
546                 if (addnew)
547                         gpl->actframe= gpencil_frame_addnew(gpl, cframe);
548                 else {
549                         /* don't do anything... this may be when no frames yet! */
550                 }
551         }
552         
553         /* return */
554         return gpl->actframe;
555 }
556
557 /* delete the given frame from a layer */
558 void gpencil_layer_delframe (bGPDlayer *gpl, bGPDframe *gpf)
559 {
560         /* error checking */
561         if (ELEM(NULL, gpl, gpf))
562                 return;
563                 
564         /* free the frame and its data */
565         free_gpencil_strokes(gpf);
566         BLI_freelinkN(&gpl->frames, gpf);
567         gpl->actframe = NULL;
568 }
569
570 /* get the active gp-layer for editing */
571 bGPDlayer *gpencil_layer_getactive (bGPdata *gpd)
572 {
573         bGPDlayer *gpl;
574         
575         /* error checking */
576         if (ELEM(NULL, gpd, gpd->layers.first))
577                 return NULL;
578                 
579         /* loop over layers until found (assume only one active) */
580         for (gpl=gpd->layers.first; gpl; gpl=gpl->next) {
581                 if (gpl->flag & GP_LAYER_ACTIVE)
582                         return gpl;
583         }
584         
585         /* no active layer found */
586         return NULL;
587 }
588
589 /* set the active gp-layer */
590 void gpencil_layer_setactive (bGPdata *gpd, bGPDlayer *active)
591 {
592         bGPDlayer *gpl;
593         
594         /* error checking */
595         if (ELEM3(NULL, gpd, gpd->layers.first, active))
596                 return;
597                 
598         /* loop over layers deactivating all */
599         for (gpl=gpd->layers.first; gpl; gpl=gpl->next)
600                 gpl->flag &= ~GP_LAYER_ACTIVE;
601         
602         /* set as active one */
603         active->flag |= GP_LAYER_ACTIVE;
604 }
605
606 /* delete the active gp-layer */
607 void gpencil_layer_delactive (bGPdata *gpd)
608 {
609         bGPDlayer *gpl= gpencil_layer_getactive(gpd);
610         
611         /* error checking */
612         if (ELEM(NULL, gpd, gpl)) 
613                 return;
614         
615         /* free layer */        
616         free_gpencil_frames(gpl);
617         BLI_freelinkN(&gpd->layers, gpl);
618
619 }
620
621 /* ************************************************** */
622 /* GREASE-PENCIL EDITING - Tools */
623
624 /* --------- Data Deletion ---------- */
625
626 /* delete the last stroke on the active layer */
627 void gpencil_delete_laststroke (bGPdata *gpd)
628 {
629         bGPDlayer *gpl= gpencil_layer_getactive(gpd);
630         bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
631         
632         gpencil_frame_delete_laststroke(gpf);
633 }
634
635 /* delete the active frame */
636 void gpencil_delete_actframe (bGPdata *gpd)
637 {
638         bGPDlayer *gpl= gpencil_layer_getactive(gpd);
639         bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
640         
641         gpencil_layer_delframe(gpl, gpf);
642 }
643
644
645
646 /* delete various grase-pencil elements 
647  *      mode:   1 - last stroke
648  *                      2 - active frame
649  *                      3 - active layer
650  */
651 void gpencil_delete_operation (short mode)
652 {
653         bGPdata *gpd;
654         
655         /* get datablock to work on */
656         gpd= gpencil_data_getactive(NULL);
657         if (gpd == NULL) return;
658         
659         switch (mode) {
660                 case 1: /* last stroke */
661                         gpencil_delete_laststroke(gpd);
662                         break;
663                 case 2: /* active frame */
664                         gpencil_delete_actframe(gpd);
665                         break;
666                 case 3: /* active layer */
667                         gpencil_layer_delactive(gpd);
668                         break;
669         }
670         
671         /* redraw and undo-push */
672         BIF_undo_push("GPencil Delete");
673         allqueue(REDRAWVIEW3D, 0);
674 }
675
676 /* display a menu for deleting different grease-pencil elements */
677 void gpencil_delete_menu (void)
678 {
679         bGPdata *gpd= gpencil_data_getactive(NULL);
680         short mode;
681         
682         /* only show menu if it will be relevant */
683         if (gpd == NULL) return;
684         
685         mode= pupmenu("Grease Pencil Erase...%t|Last Stroke%x1|Active Frame%x2|Active Layer%x3");
686         if (mode <= 0) return;
687         
688         gpencil_delete_operation(mode);
689 }
690
691 /* --------- Data Conversion ---------- */
692
693 /* convert the coordinates from the given stroke point into 3d-coordinates */
694 static void gp_strokepoint_convertcoords (bGPDstroke *gps, bGPDspoint *pt, float p3d[3])
695 {
696         if (gps->flag & GP_STROKE_3DSPACE) {
697                 /* directly use 3d-coordinates */
698                 VecCopyf(p3d, &pt->x);
699         }
700         else {
701                 short mval[2], mx, my;
702                 float *fp= give_cursor();
703                 float dvec[3];
704                 
705                 /* get screen coordinate */
706                 if (gps->flag & GP_STROKE_2DSPACE) {
707                         View2D *v2d= spacelink_get_view2d(curarea->spacedata.first);
708                         ipoco_to_areaco_noclip(v2d, &pt->x, mval);
709                 }
710                 else {
711                         mval[0]= (pt->x / 1000 * curarea->winx);
712                         mval[1]= (pt->y / 1000 * curarea->winy);
713                 }
714                 mx= mval[0]; 
715                 my= mval[1];
716                 
717                 /* convert screen coordinate to 3d coordinates 
718                  *      - method taken from editview.c - mouse_cursor() 
719                  */
720                 project_short_noclip(fp, mval);
721                 window_to_3d(dvec, mval[0]-mx, mval[1]-my);
722                 VecSubf(p3d, fp, dvec);
723         }
724 }
725
726 /* --- */
727
728 /* convert stroke to 3d path */
729 static void gp_stroke_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
730 {
731         bGPDspoint *pt;
732         Nurb *nu;
733         BPoint *bp;
734         int i;
735         
736         /* create new 'nurb' within the curve */
737         nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)");
738         
739         nu->pntsu= gps->totpoints;
740         nu->pntsv= 1;
741         nu->orderu= gps->totpoints;
742         nu->flagu= 2;   /* endpoint */
743         nu->resolu= 32;
744         
745         nu->bp= (BPoint *)MEM_callocN(sizeof(BPoint)*gps->totpoints, "bpoints");
746         
747         /* add points */
748         for (i=0, pt=gps->points, bp=nu->bp; i < gps->totpoints; i++, pt++, bp++) {
749                 float p3d[3];
750                 
751                 /* get coordinates to add at */
752                 gp_strokepoint_convertcoords(gps, pt, p3d);
753                 VecCopyf(bp->vec, p3d);
754                 
755                 /* set settings */
756                 bp->f1= SELECT;
757                 bp->radius = bp->weight = pt->pressure * gpl->thickness;
758         }
759         
760         /* add nurb to curve */
761         BLI_addtail(&cu->nurb, nu);
762 }
763
764 /* convert stroke to 3d bezier */
765 static void gp_stroke_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
766 {
767         bGPDspoint *pt;
768         Nurb *nu;
769         BezTriple *bezt;
770         int i;
771         
772         /* create new 'nurb' within the curve */
773         nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)");
774         
775         nu->pntsu= gps->totpoints;
776         nu->resolu= 12;
777         nu->resolv= 12;
778         nu->type= CU_BEZIER;
779         nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints*sizeof(BezTriple), "bezts");
780         
781         /* add points */
782         for (i=0, pt=gps->points, bezt=nu->bezt; i < gps->totpoints; i++, pt++, bezt++) {
783                 float p3d[3];
784                 
785                 /* get coordinates to add at */
786                 gp_strokepoint_convertcoords(gps, pt, p3d);
787                 
788                 /* TODO: maybe in future the handles shouldn't be in same place */
789                 VecCopyf(bezt->vec[0], p3d);
790                 VecCopyf(bezt->vec[1], p3d);
791                 VecCopyf(bezt->vec[2], p3d);
792                 
793                 /* set settings */
794                 bezt->h1= bezt->h2= HD_FREE;
795                 bezt->f1= bezt->f2= bezt->f3= SELECT;
796                 bezt->radius = bezt->weight = pt->pressure * gpl->thickness;
797         }
798         
799         /* must calculate handles or else we crash */
800         calchandlesNurb(nu);
801         
802         /* add nurb to curve */
803         BLI_addtail(&cu->nurb, nu);
804 }
805
806 /* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
807 static void gp_layer_to_curve (bGPdata *gpd, bGPDlayer *gpl, short mode)
808 {
809         bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
810         bGPDstroke *gps;
811         Object *ob;
812         Curve *cu;
813         
814         /* error checking */
815         if (ELEM3(NULL, gpd, gpl, gpf))
816                 return;
817                 
818         /* only convert if there are any strokes on this layer's frame to convert */
819         if (gpf->strokes.first == NULL)
820                 return;
821                 
822         /* initialise the curve */      
823         cu= add_curve(gpl->info, 1);
824         cu->flag |= CU_3D;
825         
826         /* init the curve object (remove rotation and assign curve data to it) */
827         add_object_draw(OB_CURVE);
828         ob= OBACT;
829         ob->loc[0]= ob->loc[1]= ob->loc[2]= 0;
830         ob->rot[0]= ob->rot[1]= ob->rot[2]= 0;
831         ob->data= cu;
832         
833         /* add points to curve */
834         for (gps= gpf->strokes.first; gps; gps= gps->next) {
835                 switch (mode) {
836                         case 1: 
837                                 gp_stroke_to_path(gpl, gps, cu);
838                                 break;
839                         case 2:
840                                 gp_stroke_to_bezier(gpl, gps, cu);
841                                 break;
842                 }
843         }
844 }
845
846 /* --- */
847
848 /* convert a stroke to a bone chain */
849 static void gp_stroke_to_bonechain (bGPDlayer *gpl, bGPDstroke *gps, bArmature *arm, ListBase *bones)
850 {
851         EditBone *ebo, *prev=NULL;
852         bGPDspoint *pt, *ptn;
853         int i;
854         
855         /* add each segment separately */
856         for (i=0, pt=gps->points, ptn=gps->points+1; i < (gps->totpoints-1); prev=ebo, i++, pt++, ptn++) {
857                 float p3da[3], p3db[3];
858                 
859                 /* get coordinates to add at */
860                 gp_strokepoint_convertcoords(gps, pt, p3da);
861                 gp_strokepoint_convertcoords(gps, ptn, p3db);
862                 
863                 /* allocate new bone */
864                 ebo= MEM_callocN(sizeof(EditBone), "eBone");
865                 
866                 VecCopyf(ebo->head, p3da);
867                 VecCopyf(ebo->tail, p3db);
868                 
869                 /* add new bone - note: sync with editarmature.c::add_editbone() */
870                 BLI_strncpy(ebo->name, "Stroke", 32);
871                 unique_editbone_name(bones, ebo->name);
872                 
873                 BLI_addtail(bones, ebo);
874                 
875                 ebo->flag |= BONE_CONNECTED;
876                 ebo->weight= 1.0F;
877                 ebo->dist= 0.25F;
878                 ebo->xwidth= 0.1;
879                 ebo->zwidth= 0.1;
880                 ebo->ease1= 1.0;
881                 ebo->ease2= 1.0;
882                 ebo->rad_head= pt->pressure * gpl->thickness * 0.1;
883                 ebo->rad_tail= ptn->pressure * gpl->thickness * 0.1;
884                 ebo->segments= 1;
885                 ebo->layer= arm->layer;
886                 
887                 /* set parenting */
888                 // TODO: also adjust roll....
889                 ebo->parent= prev;
890         }
891 }
892
893 /* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
894 static void gp_layer_to_armature (bGPdata *gpd, bGPDlayer *gpl, short mode)
895 {
896         bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
897         bGPDstroke *gps;
898         Object *ob;
899         bArmature *arm;
900         ListBase bones = {0,0};
901         
902         /* error checking */
903         if (ELEM3(NULL, gpd, gpl, gpf))
904                 return;
905                 
906         /* only convert if there are any strokes on this layer's frame to convert */
907         if (gpf->strokes.first == NULL)
908                 return;
909                 
910         /* initialise the armature */   
911         arm= add_armature(gpl->info);
912         
913         /* init the armature object (remove rotation and assign armature data to it) */
914         add_object_draw(OB_ARMATURE);
915         ob= OBACT;
916         ob->loc[0]= ob->loc[1]= ob->loc[2]= 0;
917         ob->rot[0]= ob->rot[1]= ob->rot[2]= 0;
918         ob->data= arm;
919         
920         /* convert segments to bones, strokes to bone chains */
921         for (gps= gpf->strokes.first; gps; gps= gps->next) {
922                 gp_stroke_to_bonechain(gpl, gps, arm, &bones);
923         }
924         
925         /* flush editbones to armature */
926         editbones_to_armature(&bones, ob);
927         if (bones.first) BLI_freelistN(&bones);
928 }
929
930 /* --- */
931
932 /* convert grease-pencil strokes to another representation 
933  *      mode:   1 - Active layer to path
934  *                      2 - Active layer to bezier
935  *                      3 - Active layer to armature
936  */
937 void gpencil_convert_operation (short mode)
938 {
939         bGPdata *gpd;   
940         float *fp= give_cursor();
941         
942         /* get datablock to work on */
943         gpd= gpencil_data_getactive(NULL);
944         if (gpd == NULL) return;
945         
946         /* initialise 3d-cursor correction globals */
947         initgrabz(fp[0], fp[1], fp[2]);
948         
949         /* handle selection modes */
950         switch (mode) {
951                 case 1: /* active layer only (to path) */
952                 case 2: /* active layer only (to bezier) */
953                 {
954                         bGPDlayer *gpl= gpencil_layer_getactive(gpd);
955                         gp_layer_to_curve(gpd, gpl, mode);
956                 }
957                         break;
958                 case 3: /* active layer only (to armature) */
959                 {
960                         bGPDlayer *gpl= gpencil_layer_getactive(gpd);
961                         gp_layer_to_armature(gpd, gpl, mode);
962                 }
963                         break;
964         }
965         
966         /* redraw and undo-push */
967         BIF_undo_push("GPencil Convert");
968         allqueue(REDRAWVIEW3D, 0);
969         allqueue(REDRAWOOPS, 0);
970 }
971
972 /* display a menu for converting grease-pencil strokes */
973 void gpencil_convert_menu (void)
974 {
975         bGPdata *gpd= gpencil_data_getactive(NULL);
976         short mode;
977         
978         /* only show menu if it will be relevant */
979         if (gpd == NULL) return;
980         
981         mode= pupmenu("Grease Pencil Convert %t|Active Layer To Path%x1|Active Layer to Bezier%x2|Active Layer to Armature%x3");
982         if (mode <= 0) return;
983         
984         gpencil_convert_operation(mode);
985 }
986
987 /* ************************************************** */
988 /* GREASE-PENCIL EDITING MODE - Painting */
989
990 /* ---------- 'Globals' and Defines ----------------- */
991
992 /* maximum sizes of gp-session buffer */
993 #define GP_STROKE_BUFFER_MAX    5000
994
995 /* Hardcoded sensitivity thresholds... */
996 // TODO: one day, these might be added to the UI if it is necessary
997         /* minimum number of pixels mouse should move before new point created */
998 #define MIN_MANHATTEN_PX                3       
999         /* minimum length of new segment before new point can be added */
1000 #define MIN_EUCLIDEAN_PX                20
1001
1002 /* ------ */
1003
1004 /* Temporary 'Stroke' Operation data */
1005 typedef struct tGPsdata {
1006         ScrArea *sa;            /* area where painting originated */
1007         View2D *v2d;            /* needed for GP_STROKE_2DSPACE */
1008         ImBuf *ibuf;            /* needed for GP_STROKE_2DIMAGE */
1009         
1010         bGPdata *gpd;           /* gp-datablock layer comes from */
1011         bGPDlayer *gpl;         /* layer we're working on */
1012         bGPDframe *gpf;         /* frame we're working on */
1013         
1014         short status;           /* current status of painting */
1015         short paintmode;        /* mode for painting */
1016         
1017         short mval[2];          /* current mouse-position */
1018         short mvalo[2];         /* previous recorded mouse-position */
1019         short radius;           /* radius of influence for eraser */
1020 } tGPsdata;
1021
1022 /* values for tGPsdata->status */
1023 enum {
1024         GP_STATUS_NORMAL = 0,   /* running normally */
1025         GP_STATUS_ERROR,                /* something wasn't correctly set up */
1026         GP_STATUS_DONE                  /* painting done */
1027 };
1028
1029 /* values for tGPsdata->paintmode */
1030 enum {
1031         GP_PAINTMODE_DRAW = 0,
1032         GP_PAINTMODE_ERASER
1033 };
1034
1035 /* Return flags for adding points to stroke buffer */
1036 enum {
1037         GP_STROKEADD_INVALID    = -2,           /* error occurred - insufficient info to do so */
1038         GP_STROKEADD_OVERFLOW   = -1,           /* error occurred - cannot fit any more points */
1039         GP_STROKEADD_NORMAL,                            /* point was successfully added */
1040         GP_STROKEADD_FULL                                       /* cannot add any more points to buffer */
1041 };
1042
1043 /* ---------- Stroke Editing ------------ */
1044
1045 /* clear the session buffers (call this before AND after a paint operation) */
1046 static void gp_session_validatebuffer (tGPsdata *p)
1047 {
1048         bGPdata *gpd= p->gpd;
1049         
1050         /* clear memory of buffer (or allocate it if starting a new session) */
1051         if (gpd->sbuffer)
1052                 memset(gpd->sbuffer, 0, sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX);
1053         else
1054                 gpd->sbuffer= MEM_callocN(sizeof(tGPspoint)*GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
1055         
1056         /* reset indices */
1057         gpd->sbuffer_size = 0;
1058         
1059         /* reset flags */
1060         gpd->sbuffer_sflag= 0;
1061 }
1062
1063 /* init new painting session */
1064 static void gp_session_initpaint (tGPsdata *p)
1065 {
1066         /* clear previous data (note: is on stack) */
1067         memset(p, 0, sizeof(tGPsdata));
1068         
1069         /* make sure the active view (at the starting time) is a 3d-view */
1070         if (curarea == NULL) {
1071                 p->status= GP_STATUS_ERROR;
1072                 if (G.f & G_DEBUG) 
1073                         printf("Error: No active view for painting \n");
1074                 return;
1075         }
1076         switch (curarea->spacetype) {
1077                 /* supported views first */
1078                 case SPACE_VIEW3D:
1079                 {
1080                         View3D *v3d= curarea->spacedata.first;
1081                         
1082                         /* set current area */
1083                         p->sa= curarea;
1084                         
1085                         /* check that gpencil data is allowed to be drawn */
1086                         if ((v3d->flag2 & V3D_DISPGP)==0) {
1087                                 p->status= GP_STATUS_ERROR;
1088                                 if (G.f & G_DEBUG) 
1089                                         printf("Error: In active view, Grease Pencil not shown \n");
1090                                 return;
1091                         }
1092                 }
1093                         break;
1094                 case SPACE_NODE:
1095                 {
1096                         SpaceNode *snode= curarea->spacedata.first;
1097                         
1098                         /* set current area */
1099                         p->sa= curarea;
1100                         p->v2d= &snode->v2d;
1101                         
1102                         /* check that gpencil data is allowed to be drawn */
1103                         if ((snode->flag & SNODE_DISPGP)==0) {
1104                                 p->status= GP_STATUS_ERROR;
1105                                 if (G.f & G_DEBUG) 
1106                                         printf("Error: In active view, Grease Pencil not shown \n");
1107                                 return;
1108                         }
1109                 }
1110                         break;
1111                 case SPACE_SEQ:
1112                 {
1113                         SpaceSeq *sseq= curarea->spacedata.first;
1114                         
1115                         /* set current area */
1116                         p->sa= curarea;
1117                         p->v2d= &sseq->v2d;
1118                         
1119                         /* check that gpencil data is allowed to be drawn */
1120                         if (sseq->mainb == 0) {
1121                                 p->status= GP_STATUS_ERROR;
1122                                 if (G.f & G_DEBUG) 
1123                                         printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil \n");
1124                                 return;
1125                         }
1126                         if ((sseq->flag & SEQ_DRAW_GPENCIL)==0) {
1127                                 p->status= GP_STATUS_ERROR;
1128                                 if (G.f & G_DEBUG) 
1129                                         printf("Error: In active view, Grease Pencil not shown \n");
1130                                 return;
1131                         }
1132                 }
1133                         break;  
1134                 case SPACE_IMAGE:
1135                 {
1136                         SpaceImage *sima= curarea->spacedata.first;
1137                         
1138                         /* set the current area */
1139                         p->sa= curarea;
1140                         p->v2d= &sima->v2d;
1141                         p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser);
1142                 }
1143                         break;
1144                 /* unsupported views */
1145                 default:
1146                 {
1147                         p->status= GP_STATUS_ERROR;
1148                         if (G.f & G_DEBUG) 
1149                                 printf("Error: Active view not appropriate for Grease Pencil drawing \n");
1150                         return;
1151                 }
1152                         break;
1153         }
1154         
1155         /* get gp-data */
1156         p->gpd= gpencil_data_getactive(p->sa);
1157         if (p->gpd == NULL) {
1158                 short ok;
1159                 
1160                 p->gpd= gpencil_data_addnew();
1161                 ok= gpencil_data_setactive(p->sa, p->gpd);
1162                 
1163                 /* most of the time, the following check isn't needed */
1164                 if (ok == 0) {
1165                         /* free gpencil data as it can't be used */
1166                         free_gpencil_data(p->gpd);
1167                         p->gpd= NULL;
1168                         p->status= GP_STATUS_ERROR;
1169                         if (G.f & G_DEBUG) 
1170                                 printf("Error: Could not assign newly created Grease Pencil data to active area \n");
1171                         return;
1172                 }
1173         }
1174         
1175         /* set edit flags */
1176         G.f |= G_GREASEPENCIL;
1177         
1178         /* clear out buffer (stored in gp-data) in case something contaminated it */
1179         gp_session_validatebuffer(p);
1180 }
1181
1182 /* cleanup after a painting session */
1183 static void gp_session_cleanup (tGPsdata *p)
1184 {
1185         bGPdata *gpd= p->gpd;
1186         
1187         /* error checking */
1188         if (gpd == NULL)
1189                 return;
1190         
1191         /* free stroke buffer */
1192         if (gpd->sbuffer) {
1193                 MEM_freeN(gpd->sbuffer);
1194                 gpd->sbuffer= NULL;
1195         }
1196         
1197         /* clear flags */
1198         gpd->sbuffer_size= 0;
1199         gpd->sbuffer_sflag= 0;
1200 }
1201
1202 /* check if the current mouse position is suitable for adding a new point */
1203 static short gp_stroke_filtermval (tGPsdata *p, short mval[2], short pmval[2])
1204 {
1205         short dx= abs(mval[0] - pmval[0]);
1206         short dy= abs(mval[1] - pmval[1]);
1207         
1208         /* check if mouse moved at least certain distance on both axes (best case) */
1209         if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
1210                 return 1;
1211         
1212         /* check if the distance since the last point is significant enough */
1213         // future optimisation: sqrt here may be too slow?
1214         else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX)
1215                 return 1;
1216         
1217         /* mouse 'didn't move' */
1218         else
1219                 return 0;
1220 }
1221
1222 /* convert screen-coordinates to buffer-coordinates */
1223 static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[])
1224 {
1225         bGPdata *gpd= p->gpd;
1226         
1227         /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
1228         if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) {
1229                 const short mx=mval[0], my=mval[1];
1230                 float *fp= give_cursor();
1231                 float dvec[3];
1232                 
1233                 /* method taken from editview.c - mouse_cursor() */
1234                 project_short_noclip(fp, mval);
1235                 window_to_3d(dvec, mval[0]-mx, mval[1]-my);
1236                 VecSubf(out, fp, dvec);
1237         }
1238         
1239         /* 2d - on 'canvas' (assume that p->v2d is set) */
1240         else if ((gpd->sbuffer_sflag & GP_STROKE_2DSPACE) && (p->v2d)) {
1241                 float x, y;
1242                 
1243                 areamouseco_to_ipoco(p->v2d, mval, &x, &y);
1244                 
1245                 out[0]= x;
1246                 out[1]= y;
1247         }
1248         
1249         /* 2d - on image 'canvas' (assume that p->v2d is set) */
1250         else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) && (p->v2d) ) 
1251         {
1252                 /* for now - space specific */
1253                 switch (p->sa->spacetype) {
1254                         case SPACE_SEQ: /* sequencer */
1255                         {
1256                                 SpaceSeq *sseq= (SpaceSeq *)p->sa->spacedata.first;
1257                                 int sizex, sizey, offsx, offsy, rectx, recty;
1258                                 float zoom, zoomx, zoomy;
1259                                 
1260                                 /* calculate zoom factor */
1261                                 zoom= SEQ_ZOOM_FAC(sseq->zoom);
1262                                 if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
1263                                         zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp);
1264                                         zoomy = zoom;
1265                                 } 
1266                                 else
1267                                         zoomx = zoomy = zoom;
1268                                 
1269                                 /* calculate rect size */
1270                                 rectx= (G.scene->r.size*G.scene->r.xsch)/100;
1271                                 recty= (G.scene->r.size*G.scene->r.ysch)/100; 
1272                                 sizex= zoomx * rectx;
1273                                 sizey= zoomy * recty;
1274                                 offsx= (p->sa->winx-sizex)/2 + sseq->xof;
1275                                 offsy= (p->sa->winy-sizey)/2 + sseq->yof;
1276                                 
1277                                 /* calculate new points */
1278                                 out[0]= (float)(mval[0] - offsx) / (float)sizex;
1279                                 out[1]= (float)(mval[1] - offsy) / (float)sizey;
1280                         }
1281                                 break;
1282                                 
1283                         default: /* just use raw mouse coordinates - BAD! */
1284                                 out[0]= mval[0];
1285                                 out[1]= mval[1];
1286                                 break;
1287                 }               
1288         }
1289         
1290         /* 2d - relative to screen (viewport area) */
1291         else {
1292                 out[0] = (float)(mval[0]) / (float)(p->sa->winx) * 1000;
1293                 out[1] = (float)(mval[1]) / (float)(p->sa->winy) * 1000;
1294         }
1295 }
1296
1297 /* add current stroke-point to buffer (returns whether point was successfully added) */
1298 static short gp_stroke_addpoint (tGPsdata *p, short mval[2], float pressure)
1299 {
1300         bGPdata *gpd= p->gpd;
1301         tGPspoint *pt;
1302         
1303         /* check if still room in buffer */
1304         if (gpd->sbuffer_size >= GP_STROKE_BUFFER_MAX)
1305                 return GP_STROKEADD_OVERFLOW;
1306         
1307         /* get pointer to destination point */
1308         pt= ((tGPspoint *)(gpd->sbuffer) + gpd->sbuffer_size);
1309         
1310         /* store settings */
1311         pt->x= mval[0];
1312         pt->y= mval[1];
1313         pt->pressure= pressure;
1314         
1315         /* increment counters */
1316         gpd->sbuffer_size++;
1317         
1318         /* check if another operation can still occur */
1319         if (gpd->sbuffer_size == GP_STROKE_BUFFER_MAX)
1320                 return GP_STROKEADD_FULL;
1321         else
1322                 return GP_STROKEADD_NORMAL;
1323 }
1324
1325 /* make a new stroke from the buffer data */
1326 static void gp_stroke_newfrombuffer (tGPsdata *p)
1327 {
1328         bGPdata *gpd= p->gpd;
1329         bGPDstroke *gps;
1330         bGPDspoint *pt;
1331         tGPspoint *ptc;
1332         int i, totelem;
1333
1334         /* macro to test if only converting endpoints  */       
1335         #define GP_BUFFER2STROKE_ENDPOINTS ((gpd->flag & GP_DATA_EDITPAINT) && (G.qual & LR_CTRLKEY))
1336         
1337         /* get total number of points to allocate space for:
1338          *      - in 'Draw Mode', holding the Ctrl-Modifier will only take endpoints
1339          *      - otherwise, do whole stroke
1340          */
1341         if (GP_BUFFER2STROKE_ENDPOINTS)
1342                 totelem = (gpd->sbuffer_size >= 2) ? 2: gpd->sbuffer_size;
1343         else
1344                 totelem = gpd->sbuffer_size;
1345         
1346         /* exit with error if no valid points from this stroke */
1347         if (totelem == 0) {
1348                 if (G.f & G_DEBUG) 
1349                         printf("Error: No valid points in stroke buffer to convert (tot=%d) \n", gpd->sbuffer_size);
1350                 return;
1351         }
1352         
1353         /* allocate memory for a new stroke */
1354         gps= MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
1355         
1356         /* allocate enough memory for a continuous array for storage points */
1357         pt= gps->points= MEM_callocN(sizeof(bGPDspoint)*totelem, "gp_stroke_points");
1358         
1359         /* copy appropriate settings for stroke */
1360         gps->totpoints= totelem;
1361         gps->thickness= p->gpl->thickness;
1362         gps->flag= gpd->sbuffer_sflag;
1363         
1364         /* copy points from the buffer to the stroke */
1365         if (GP_BUFFER2STROKE_ENDPOINTS) {
1366                 /* 'Draw Mode' + Ctrl-Modifier - only endpoints */
1367                 {
1368                         /* first point */
1369                         ptc= gpd->sbuffer;
1370                         
1371                         /* convert screen-coordinates to appropriate coordinates (and store them) */
1372                         gp_stroke_convertcoords(p, &ptc->x, &pt->x);
1373                         
1374                         /* copy pressure */
1375                         pt->pressure= ptc->pressure;
1376                         
1377                         pt++;
1378                 }
1379                         
1380                 if (totelem == 2) {
1381                         /* last point if applicable */
1382                         ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1);
1383                         
1384                         /* convert screen-coordinates to appropriate coordinates (and store them) */
1385                         gp_stroke_convertcoords(p, &ptc->x, &pt->x);
1386                         
1387                         /* copy pressure */
1388                         pt->pressure= ptc->pressure;
1389                 }
1390         }
1391         else {
1392                 /* convert all points (normal behaviour) */
1393                 for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) {
1394                         /* convert screen-coordinates to appropriate coordinates (and store them) */
1395                         gp_stroke_convertcoords(p, &ptc->x, &pt->x);
1396                         
1397                         /* copy pressure */
1398                         pt->pressure= ptc->pressure;
1399                         
1400                         pt++;
1401                 }
1402         }
1403         
1404         /* add stroke to frame */
1405         BLI_addtail(&p->gpf->strokes, gps);
1406         
1407         /* undefine macro to test if only converting endpoints  */      
1408         #undef GP_BUFFER2STROKE_ENDPOINTS
1409 }
1410
1411 /* --- 'Eraser' for 'Paint' Tool ------ */
1412
1413 /* eraser tool - remove segment from stroke/split stroke (after lasso inside) */
1414 static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i)
1415 {
1416         bGPDspoint *pt_tmp= gps->points;
1417         bGPDstroke *gsn = NULL;
1418
1419         /* if stroke only had two points, get rid of stroke */
1420         if (gps->totpoints == 2) {
1421                 /* free stroke points, then stroke */
1422                 MEM_freeN(pt_tmp);
1423                 BLI_freelinkN(&gpf->strokes, gps);
1424                 
1425                 /* nothing left in stroke, so stop */
1426                 return 1;
1427         }
1428
1429         /* if last segment, just remove segment from the stroke */
1430         else if (i == gps->totpoints - 2) {
1431                 /* allocate new points array, and assign most of the old stroke there */
1432                 gps->totpoints--;
1433                 gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points");
1434                 memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*gps->totpoints);
1435                 
1436                 /* free temp buffer */
1437                 MEM_freeN(pt_tmp);
1438                 
1439                 /* nothing left in stroke, so stop */
1440                 return 1;
1441         }
1442
1443         /* if first segment, just remove segment from the stroke */
1444         else if (i == 0) {
1445                 /* allocate new points array, and assign most of the old stroke there */
1446                 gps->totpoints--;
1447                 gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points");
1448                 memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint)*gps->totpoints);
1449                 
1450                 /* free temp buffer */
1451                 MEM_freeN(pt_tmp);
1452                 
1453                 /* no break here, as there might still be stuff to remove in this stroke */
1454                 return 0;
1455         }
1456
1457         /* segment occurs in 'middle' of stroke, so split */
1458         else {
1459                 /* duplicate stroke, and assign 'later' data to that stroke */
1460                 gsn= MEM_dupallocN(gps);
1461                 gsn->prev= gsn->next= NULL;
1462                 BLI_insertlinkafter(&gpf->strokes, gps, gsn);
1463                 
1464                 gsn->totpoints= gps->totpoints - i;
1465                 gsn->points= MEM_callocN(sizeof(bGPDspoint)*gsn->totpoints, "gp_stroke_points");
1466                 memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint)*gsn->totpoints);
1467                 
1468                 /* adjust existing stroke  */
1469                 gps->totpoints= i;
1470                 gps->points= MEM_callocN(sizeof(bGPDspoint)*gps->totpoints, "gp_stroke_points");
1471                 memcpy(gps->points, pt_tmp, sizeof(bGPDspoint)*i);
1472                 
1473                 /* free temp buffer */
1474                 MEM_freeN(pt_tmp);
1475                 
1476                 /* nothing left in stroke, so stop */
1477                 return 1;
1478         }
1479 }
1480
1481 /* eraser tool - check if part of stroke occurs within last segment drawn by eraser */
1482 static short gp_stroke_eraser_strokeinside (short mval[], short mvalo[], short rad, short x0, short y0, short x1, short y1)
1483 {
1484         /* simple within-radius check for now */
1485         if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1))
1486                 return 1;
1487         
1488         /* not inside */
1489         return 0;
1490
1491
1492 /* eraser tool - evaluation per stroke */
1493 static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], short rad, rcti *rect, bGPDframe *gpf, bGPDstroke *gps)
1494 {
1495         bGPDspoint *pt1, *pt2;
1496         short x0=0, y0=0, x1=0, y1=0;
1497         short xyval[2];
1498         int i;
1499         
1500         if (gps->totpoints == 0) {
1501                 /* just free stroke */
1502                 if (gps->points) 
1503                         MEM_freeN(gps->points);
1504                 BLI_freelinkN(&gpf->strokes, gps);
1505         }
1506         else if (gps->totpoints == 1) {
1507                 /* get coordinates */
1508                 if (gps->flag & GP_STROKE_3DSPACE) {
1509                         project_short(&gps->points->x, xyval);
1510                         x0= xyval[0];
1511                         y0= xyval[1];
1512                 }
1513                 else if (gps->flag & GP_STROKE_2DSPACE) {                       
1514                         ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval);
1515                         x0= xyval[0];
1516                         y0= xyval[1];
1517                 }
1518                 else if (gps->flag & GP_STROKE_2DIMAGE) {                       
1519                         ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval);
1520                         x0= xyval[0];
1521                         y0= xyval[1];
1522                 }
1523                 else {
1524                         x0= (gps->points->x / 1000 * p->sa->winx);
1525                         y0= (gps->points->y / 1000 * p->sa->winy);
1526                 }
1527                 
1528                 /* do boundbox check first */
1529                 if (BLI_in_rcti(rect, x0, y0)) {
1530                         /* only check if point is inside */
1531                         if ( ((x0-mval[0])*(x0-mval[0]) + (y0-mval[1])*(y0-mval[1])) <= rad*rad ) {
1532                                 /* free stroke */
1533                                 MEM_freeN(gps->points);
1534                                 BLI_freelinkN(&gpf->strokes, gps);
1535                         }
1536                 }
1537         }
1538         else {  
1539                 /* loop over the points in the stroke, checking for intersections 
1540                  *      - an intersection will require the stroke to be split
1541                  */
1542                 for (i=0; (i+1) < gps->totpoints; i++) {
1543                         /* get points to work with */
1544                         pt1= gps->points + i;
1545                         pt2= gps->points + i + 1;
1546                         
1547                         /* get coordinates */
1548                         if (gps->flag & GP_STROKE_3DSPACE) {
1549                                 project_short(&pt1->x, xyval);
1550                                 x0= xyval[0];
1551                                 y0= xyval[1];
1552                                 
1553                                 project_short(&pt2->x, xyval);
1554                                 x1= xyval[0];
1555                                 y1= xyval[1];
1556                         }
1557                         else if (gps->flag & GP_STROKE_2DSPACE) {
1558                                 ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval);
1559                                 x0= xyval[0];
1560                                 y0= xyval[1];
1561                                 
1562                                 ipoco_to_areaco_noclip(p->v2d, &pt2->x, xyval);
1563                                 x1= xyval[0];
1564                                 y1= xyval[1];
1565                         }
1566                         else if (gps->flag & GP_STROKE_2DIMAGE) {
1567                                 ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval);
1568                                 x0= xyval[0];
1569                                 y0= xyval[1];
1570                                 
1571                                 ipoco_to_areaco_noclip(p->v2d, &pt2->x, xyval);
1572                                 x1= xyval[0];
1573                                 y1= xyval[1];
1574                         }
1575                         else {
1576                                 x0= (pt1->x / 1000 * p->sa->winx);
1577                                 y0= (pt1->y / 1000 * p->sa->winy);
1578                                 x1= (pt2->x / 1000 * p->sa->winx);
1579                                 y1= (pt2->y / 1000 * p->sa->winy);
1580                         }
1581                         
1582                         /* check that point segment of the boundbox of the eraser stroke */
1583                         if (BLI_in_rcti(rect, x0, y0) || BLI_in_rcti(rect, x1, y1)) {
1584                                 /* check if point segment of stroke had anything to do with
1585                                  * eraser region  (either within stroke painted, or on its lines)
1586                                  *      - this assumes that linewidth is irrelevant
1587                                  */
1588                                 if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) {
1589                                         /* if function returns true, break this loop (as no more point to check) */
1590                                         if (gp_stroke_eraser_splitdel(gpf, gps, i))
1591                                                 break;
1592                                 }
1593                         }
1594                 }
1595         }
1596 }
1597
1598 /* erase strokes which fall under the eraser strokes */
1599 static void gp_stroke_doeraser (tGPsdata *p)
1600 {
1601         bGPDframe *gpf= p->gpf;
1602         bGPDstroke *gps, *gpn;
1603         rcti rect;
1604         
1605         /* rect is rectangle of eraser */
1606         rect.xmin= p->mval[0] - p->radius;
1607         rect.ymin= p->mval[1] - p->radius;
1608         rect.xmax= p->mval[0] + p->radius;
1609         rect.ymax= p->mval[1] + p->radius;
1610         
1611         /* loop over strokes, checking segments for intersections */
1612         for (gps= gpf->strokes.first; gps; gps= gpn) {
1613                 gpn= gps->next;
1614                 gp_stroke_eraser_dostroke(p, p->mval, p->mvalo, p->radius, &rect, gpf, gps);
1615         }
1616 }
1617
1618 /* ---------- 'Paint' Tool ------------ */
1619
1620 /* init new stroke */
1621 static void gp_paint_initstroke (tGPsdata *p, short paintmode)
1622 {       
1623         /* get active layer (or add a new one if non-existent) */
1624         p->gpl= gpencil_layer_getactive(p->gpd);
1625         if (p->gpl == NULL)
1626                 p->gpl= gpencil_layer_addnew(p->gpd);
1627         if (p->gpl->flag & GP_LAYER_LOCKED) {
1628                 p->status= GP_STATUS_ERROR;
1629                 if (G.f & G_DEBUG)
1630                         printf("Error: Cannot paint on locked layer \n");
1631                 return;
1632         }
1633                 
1634         /* get active frame (add a new one if not matching frame) */
1635         p->gpf= gpencil_layer_getframe(p->gpl, CFRA, 1);
1636         if (p->gpf == NULL) {
1637                 p->status= GP_STATUS_ERROR;
1638                 if (G.f & G_DEBUG) 
1639                         printf("Error: No frame created (gpencil_paint_init) \n");
1640                 return;
1641         }
1642         else
1643                 p->gpf->flag |= GP_FRAME_PAINT;
1644         
1645         /* set 'eraser' for this stroke if using eraser */
1646         p->paintmode= paintmode;
1647         if (p->paintmode == GP_PAINTMODE_ERASER)
1648                 p->gpd->sbuffer_sflag |= GP_STROKE_ERASER;
1649         
1650         /* check if points will need to be made in view-aligned space */
1651         if (p->gpd->flag & GP_DATA_VIEWALIGN) {
1652                 switch (p->sa->spacetype) {
1653                         case SPACE_VIEW3D:
1654                         {
1655                                 float *fp= give_cursor();
1656                                 initgrabz(fp[0], fp[1], fp[2]);
1657                                 
1658                                 p->gpd->sbuffer_sflag |= GP_STROKE_3DSPACE;
1659                         }
1660                                 break;
1661                         case SPACE_NODE:
1662                         {
1663                                 p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE;
1664                         }
1665                                 break;
1666                         case SPACE_SEQ:
1667                         {
1668                                 /* for now, this is not applicable here... */
1669                                 p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE;
1670                         }
1671                                 break;
1672                         case SPACE_IMAGE:
1673                         {
1674                                 /* check if any ibuf available */
1675                                 if (p->ibuf)
1676                                         p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE;
1677                         }
1678                                 break;
1679                 }
1680         }
1681 }
1682
1683 /* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
1684 static void gp_paint_strokeend (tGPsdata *p)
1685 {
1686         /* check if doing eraser or not */
1687         if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
1688                 /* transfer stroke to frame */
1689                 gp_stroke_newfrombuffer(p);
1690         }
1691         
1692         /* clean up buffer now */
1693         gp_session_validatebuffer(p);
1694 }
1695
1696 /* finish off stroke painting operation */
1697 static void gp_paint_cleanup (tGPsdata *p)
1698 {
1699         /* finish off a stroke */
1700         gp_paint_strokeend(p);
1701         
1702         /* "unlock" frame */
1703         p->gpf->flag &= ~GP_FRAME_PAINT;
1704         
1705         /* add undo-push so stroke can be undone */
1706         /* FIXME: currently disabled, as it's impossible to get this working nice
1707          * as gpenci data is on currently screen-level (which isn't saved to undo files)
1708          */
1709         //BIF_undo_push("GPencil Stroke");
1710         
1711         /* force redraw after drawing action */
1712         force_draw_plus(SPACE_ACTION, 0);
1713 }
1714
1715 /* -------- */
1716
1717 /* main call to paint a new stroke */
1718 short gpencil_paint (short mousebutton, short paintmode)
1719 {
1720         tGPsdata p;
1721         float opressure, pressure;
1722         short ok = GP_STROKEADD_NORMAL;
1723         
1724         /* init paint-data */
1725         gp_session_initpaint(&p);
1726         if (p.status == GP_STATUS_ERROR) {
1727                 gp_session_cleanup(&p);
1728                 return 0;
1729         }
1730         gp_paint_initstroke(&p, paintmode);
1731         if (p.status == GP_STATUS_ERROR) {
1732                 gp_session_cleanup(&p);
1733                 return 0;
1734         }
1735         
1736         /* set cursor to indicate drawing */
1737         setcursor_space(p.sa->spacetype, CURSOR_VPAINT);
1738         
1739         /* init drawing-device settings */
1740         getmouseco_areawin(p.mval);
1741         pressure = get_pressure();
1742         
1743         p.mvalo[0]= p.mval[0];
1744         p.mvalo[1]= p.mval[1];
1745         opressure= pressure;
1746         
1747         /* radius for eraser circle is thickness^2 */
1748         p.radius= p.gpl->thickness * p.gpl->thickness;
1749         
1750         /* start drawing eraser-circle (if applicable) */
1751         if (paintmode == GP_PAINTMODE_ERASER)
1752                 draw_sel_circle(p.mval, NULL, p.radius, p.radius, 0); // draws frontbuffer, but sets backbuf again
1753         
1754         /* only allow painting of single 'dots' if: 
1755          *      - pressure is not excessive (as it can be on some windows tablets)
1756          *      - draw-mode for active datablock is turned on
1757          *      - not erasing
1758          */
1759         if (paintmode != GP_PAINTMODE_ERASER) {
1760                 if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { 
1761                         gp_stroke_addpoint(&p, p.mval, pressure);
1762                 }
1763         }
1764         
1765         /* paint loop */
1766         do {
1767                 /* get current user input */
1768                 getmouseco_areawin(p.mval);
1769                 pressure = get_pressure();
1770                 
1771                 /* only add current point to buffer if mouse moved (otherwise wait until it does) */
1772                 if (paintmode == GP_PAINTMODE_ERASER) {
1773                         /* do 'live' erasing now */
1774                         gp_stroke_doeraser(&p);
1775                         
1776                         draw_sel_circle(p.mval, p.mvalo, p.radius, p.radius, 0);
1777                         force_draw(0);
1778                         
1779                         p.mvalo[0]= p.mval[0];
1780                         p.mvalo[1]= p.mval[1];
1781                 }
1782                 else if (gp_stroke_filtermval(&p, p.mval, p.mvalo)) {
1783                         /* try to add point */
1784                         ok= gp_stroke_addpoint(&p, p.mval, pressure);
1785                         
1786                         /* handle errors while adding point */
1787                         if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
1788                                 /* finish off old stroke */
1789                                 gp_paint_strokeend(&p);
1790                                 
1791                                 /* start a new stroke, starting from previous point */
1792                                 gp_stroke_addpoint(&p, p.mvalo, opressure);
1793                                 ok= gp_stroke_addpoint(&p, p.mval, pressure);
1794                         }
1795                         else if (ok == GP_STROKEADD_INVALID) {
1796                                 /* the painting operation cannot continue... */
1797                                 error("Cannot paint stroke");
1798                                 p.status = GP_STATUS_ERROR;
1799                                 
1800                                 if (G.f & G_DEBUG) 
1801                                         printf("Error: Grease-Pencil Paint - Add Point Invalid \n");
1802                                 break;
1803                         }
1804                         force_draw(0);
1805                         
1806                         p.mvalo[0]= p.mval[0];
1807                         p.mvalo[1]= p.mval[1];
1808                         opressure= pressure;
1809                 }
1810                 else
1811                         BIF_wait_for_statechange();
1812                 
1813                 /* do mouse checking at the end, so don't check twice, and potentially
1814                  * miss a short tap 
1815                  */
1816         } while (get_mbut() & mousebutton);
1817         
1818         /* clear edit flags */
1819         G.f &= ~G_GREASEPENCIL;
1820         
1821         /* restore cursor to indicate end of drawing */
1822         setcursor_space(p.sa->spacetype, CURSOR_STD);
1823         
1824         /* check size of buffer before cleanup, to determine if anything happened here */
1825         if (paintmode == GP_PAINTMODE_ERASER) {
1826                 ok= 1; // fixme
1827                 draw_sel_circle(NULL, p.mvalo, 0, p.radius, 0);
1828         }
1829         else
1830                 ok= p.gpd->sbuffer_size;
1831         
1832         /* cleanup */
1833         gp_paint_cleanup(&p);
1834         gp_session_cleanup(&p);
1835         
1836         /* done! return if a stroke was successfully added */
1837         return ok;
1838 }
1839
1840
1841 /* All event (loops) handling checking if stroke drawing should be initiated
1842  * should call this function.
1843  */
1844 short gpencil_do_paint (ScrArea *sa, short mbut)
1845 {
1846         bGPdata *gpd = gpencil_data_getactive(sa);
1847         short retval= 0;
1848         
1849         /* check if possible to do painting */
1850         if (gpd == NULL) 
1851                 return 0;
1852         
1853         /* currently, we will only 'paint' if:
1854          *      1. draw-mode on gpd is set (for accessibility reasons)
1855          *              a) single dots are only available by this method if a single click is made
1856          *              b) a straight line is drawn if ctrl-modifier is held (check is done when stroke is converted!)
1857          *      2. if shift-modifier is held + lmb -> 'quick paint'
1858          *
1859          *      OR
1860          * 
1861          * draw eraser stroke if:
1862          *      1. using the eraser on a tablet
1863          *      2. draw-mode on gpd is set (for accessiblity reasons)
1864          *              (eraser is mapped to right-mouse)
1865          *      3. Alt + 'select' mouse-button
1866          *              i.e.  if LMB = select: Alt-LMB
1867          *                        if RMB = select: Alt-RMB
1868          */
1869         if (get_activedevice() == 2) {
1870                 /* eraser on a tablet - always try to erase strokes */
1871                 retval = gpencil_paint(mbut, GP_PAINTMODE_ERASER);
1872         }
1873         else if (gpd->flag & GP_DATA_EDITPAINT) {
1874                 /* try to paint/erase */
1875                 if (mbut == L_MOUSE)
1876                         retval = gpencil_paint(mbut, GP_PAINTMODE_DRAW);
1877                 else if (mbut == R_MOUSE)
1878                         retval = gpencil_paint(mbut, GP_PAINTMODE_ERASER);
1879         }
1880         else if (!(gpd->flag & GP_DATA_LMBPLOCK)) {
1881                 /* try to paint/erase as not locked */
1882                 if ((G.qual == LR_SHIFTKEY) && (mbut == L_MOUSE)) {
1883                         retval = gpencil_paint(mbut, GP_PAINTMODE_DRAW);
1884                 }
1885                 else if (G.qual == LR_ALTKEY) {
1886                         if ((U.flag & USER_LMOUSESELECT) && (mbut == L_MOUSE))
1887                                 retval = gpencil_paint(mbut, GP_PAINTMODE_ERASER);
1888                         else if (!(U.flag & USER_LMOUSESELECT) && (mbut == R_MOUSE))
1889                                 retval = gpencil_paint(mbut, GP_PAINTMODE_ERASER);
1890                 }
1891         }
1892         
1893         /* return result of trying to paint */
1894         return retval;
1895 }
1896
1897 /* ************************************************** */