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