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