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