Code cleanup - Removing/commenting out various bits of legacy cruft related to
[blender.git] / source / blender / editors / gpencil / drawgpencil.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008, Blender Foundation
19  * This is a new part of Blender
20  *
21  * Contributor(s): Joshua Leung
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/gpencil/drawgpencil.c
27  *  \ingroup edgpencil
28  */
29
30  
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <math.h>
36 #include <float.h>
37
38 #include "BLO_sys_types.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43
44 #include "DNA_gpencil_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_screen_types.h"
47 #include "DNA_space_types.h"
48 #include "DNA_view3d_types.h"
49
50 #include "BKE_context.h"
51 #include "BKE_global.h"
52 #include "BKE_gpencil.h"
53
54 #include "WM_api.h"
55
56 #include "BIF_gl.h"
57 #include "BIF_glutil.h"
58
59 #include "ED_gpencil.h"
60 #include "ED_sequencer.h"
61 #include "ED_view3d.h"
62
63 #include "gpencil_intern.h"
64
65 /* ************************************************** */
66 /* GREASE PENCIL DRAWING */
67
68 /* ----- General Defines ------ */
69
70 /* flags for sflag */
71 typedef enum eDrawStrokeFlags {
72         GP_DRAWDATA_NOSTATUS    = (1 << 0),   /* don't draw status info */
73         GP_DRAWDATA_ONLY3D      = (1 << 1),   /* only draw 3d-strokes */
74         GP_DRAWDATA_ONLYV2D     = (1 << 2),   /* only draw 'canvas' strokes */
75         GP_DRAWDATA_ONLYI2D     = (1 << 3),   /* only draw 'image' strokes */
76         GP_DRAWDATA_IEDITHACK   = (1 << 4),   /* special hack for drawing strokes in Image Editor (weird coordinates) */
77         GP_DRAWDATA_NO_XRAY     = (1 << 5),   /* don't draw xray in 3D view (which is default) */
78 } eDrawStrokeFlags;
79
80
81
82 /* thickness above which we should use special drawing */
83 #define GP_DRAWTHICKNESS_SPECIAL    3
84
85 /* ----- Tool Buffer Drawing ------ */
86
87 /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
88 static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickness, short dflag, short sflag)
89 {
90         tGPspoint *pt;
91         int i;
92         
93         /* error checking */
94         if ((points == NULL) || (totpoints <= 0))
95                 return;
96         
97         /* check if buffer can be drawn */
98         if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
99                 return;
100         
101         /* if drawing a single point, draw it larger */ 
102         if (totpoints == 1) {           
103                 /* draw point */
104                 glBegin(GL_POINTS);
105                 glVertex2iv(&points->x);
106                 glEnd();
107         }
108         else if (sflag & GP_STROKE_ERASER) {
109                 /* don't draw stroke at all! */
110         }
111         else {
112                 float oldpressure = points[0].pressure;
113                 
114                 /* draw stroke curve */
115                 if (G.debug & G_DEBUG) setlinestyle(2);
116
117                 glLineWidth(oldpressure * thickness);
118                 glBegin(GL_LINE_STRIP);
119
120                 for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
121                         /* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
122                          * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
123                          */
124                         if (fabsf(pt->pressure - oldpressure) > 0.2f) {
125                                 glEnd();
126                                 glLineWidth(pt->pressure * thickness);
127                                 glBegin(GL_LINE_STRIP);
128                                 
129                                 /* need to roll-back one point to ensure that there are no gaps in the stroke */
130                                 if (i != 0) glVertex2iv(&(pt - 1)->x);
131
132                                 /* now the point we want... */
133                                 glVertex2iv(&pt->x);
134                                 
135                                 oldpressure = pt->pressure;
136                         }
137                         else
138                                 glVertex2iv(&pt->x);
139                 }
140                 glEnd();
141
142                 /* reset for predictable OpenGL context */
143                 glLineWidth(1.0f);
144                 
145                 if (G.debug & G_DEBUG) setlinestyle(0);
146         }
147 }
148
149 /* ----- Existing Strokes Drawing (3D and Point) ------ */
150
151 /* draw a given stroke - just a single dot (only one point) */
152 static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dflag, short sflag, int offsx, int offsy, int winx, int winy)
153 {
154         /* draw point */
155         if (sflag & GP_STROKE_3DSPACE) {
156                 glBegin(GL_POINTS);
157                 glVertex3fv(&points->x);
158                 glEnd();
159         }
160         else {
161                 float co[2];
162                 
163                 /* get coordinates of point */
164                 if (sflag & GP_STROKE_2DSPACE) {
165                         co[0] = points->x;
166                         co[1] = points->y;
167                 }
168                 else if (sflag & GP_STROKE_2DIMAGE) {
169                         co[0] = (points->x * winx) + offsx;
170                         co[1] = (points->y * winy) + offsy;
171                 }
172                 else {
173                         co[0] = (points->x / 100 * winx) + offsx;
174                         co[1] = (points->y / 100 * winy) + offsy;
175                 }
176                 
177                 /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok
178                  *  - also mandatory in if Image Editor 'image-based' dot
179                  */
180                 if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) ||
181                      ((dflag & GP_DRAWDATA_IEDITHACK) && (sflag & GP_STROKE_2DSPACE)) )
182                 {
183                         glBegin(GL_POINTS);
184                         glVertex2fv(co);
185                         glEnd();
186                 }
187                 else {
188                         /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */
189                         GLUquadricObj *qobj = gluNewQuadric(); 
190                         
191                         gluQuadricDrawStyle(qobj, GLU_FILL); 
192                         
193                         /* need to translate drawing position, but must reset after too! */
194                         glTranslatef(co[0], co[1], 0.0);
195                         gluDisk(qobj, 0.0,  thickness, 32, 1); 
196                         glTranslatef(-co[0], -co[1], 0.0);
197                         
198                         gluDeleteQuadric(qobj);
199                 }
200         }
201 }
202
203 /* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
204 static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, short debug)
205 {
206         bGPDspoint *pt;
207         float oldpressure = 0.0f;
208         int i;
209         
210         /* draw stroke curve */
211         glBegin(GL_LINE_STRIP);
212         for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
213                 /* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
214                  * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
215                  */
216                 if (fabsf(pt->pressure - oldpressure) > 0.2f) {
217                         glEnd();
218                         glLineWidth(pt->pressure * thickness);
219                         glBegin(GL_LINE_STRIP);
220                         
221                         /* need to roll-back one point to ensure that there are no gaps in the stroke */
222                         if (i != 0) glVertex3fv(&(pt - 1)->x);
223                         
224                         /* now the point we want... */
225                         glVertex3fv(&pt->x);
226                         
227                         oldpressure = pt->pressure;
228                 }
229                 else {
230                         glVertex3fv(&pt->x);
231                 }
232         }
233         glEnd();
234         
235         /* draw debug points of curve on top? */
236         if (debug) {
237                 glBegin(GL_POINTS);
238                 for (i = 0, pt = points; i < totpoints && pt; i++, pt++)
239                         glVertex3fv(&pt->x);
240                 glEnd();
241         }
242 }
243
244 /* ----- Fancy 2D-Stroke Drawing ------ */
245
246 /* draw a given stroke in 2d */
247 static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
248                            short debug, int offsx, int offsy, int winx, int winy)
249 {
250         /* otherwise thickness is twice that of the 3D view */
251         float thickness = (float)thickness_s * 0.5f;
252
253         /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better
254          *  - 'smooth' opengl lines are also required if Image Editor 'image-based' stroke
255          */
256         if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || 
257              ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) )
258         {
259                 bGPDspoint *pt;
260                 int i;
261                 
262                 glBegin(GL_LINE_STRIP);
263                 for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
264                         if (sflag & GP_STROKE_2DSPACE) {
265                                 glVertex2f(pt->x, pt->y);
266                         }
267                         else if (sflag & GP_STROKE_2DIMAGE) {
268                                 const float x = (pt->x * winx) + offsx;
269                                 const float y = (pt->y * winy) + offsy;
270                                 
271                                 glVertex2f(x, y);
272                         }
273                         else {
274                                 const float x = (pt->x / 100 * winx) + offsx;
275                                 const float y = (pt->y / 100 * winy) + offsy;
276                                 
277                                 glVertex2f(x, y);
278                         }
279                 }
280                 glEnd();
281         }
282         
283         /* tessellation code - draw stroke as series of connected quads with connection
284          * edges rotated to minimise shrinking artifacts, and rounded endcaps
285          */
286         else {
287                 bGPDspoint *pt1, *pt2;
288                 float pm[2];
289                 int i;
290                 
291                 glShadeModel(GL_FLAT);
292                 glBegin(GL_QUADS);
293                 
294                 for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) {
295                         float s0[2], s1[2];     /* segment 'center' points */
296                         float t0[2], t1[2];     /* tessellated coordinates */
297                         float m1[2], m2[2];     /* gradient and normal */
298                         float mt[2], sc[2];     /* gradient for thickness, point for end-cap */
299                         float pthick;           /* thickness at segment point */
300                         
301                         /* get x and y coordinates from points */
302                         if (sflag & GP_STROKE_2DSPACE) {
303                                 s0[0] = pt1->x;      s0[1] = pt1->y;
304                                 s1[0] = pt2->x;      s1[1] = pt2->y;
305                         }
306                         else if (sflag & GP_STROKE_2DIMAGE) {
307                                 s0[0] = (pt1->x * winx) + offsx;
308                                 s0[1] = (pt1->y * winy) + offsy;
309                                 s1[0] = (pt2->x * winx) + offsx;
310                                 s1[1] = (pt2->y * winy) + offsy;
311                         }
312                         else {
313                                 s0[0] = (pt1->x / 100 * winx) + offsx;
314                                 s0[1] = (pt1->y / 100 * winy) + offsy;
315                                 s1[0] = (pt2->x / 100 * winx) + offsx;
316                                 s1[1] = (pt2->y / 100 * winy) + offsy;
317                         }               
318                         
319                         /* calculate gradient and normal - 'angle'=(ny/nx) */
320                         m1[1] = s1[1] - s0[1];
321                         m1[0] = s1[0] - s0[0];
322                         normalize_v2(m1);
323                         m2[1] = -m1[0];
324                         m2[0] = m1[1];
325                         
326                         /* always use pressure from first point here */
327                         pthick = (pt1->pressure * thickness);
328                         
329                         /* if the first segment, start of segment is segment's normal */
330                         if (i == 0) {
331                                 /* draw start cap first 
332                                  *      - make points slightly closer to center (about halfway across) 
333                                  */                             
334                                 mt[0] = m2[0] * pthick * 0.5f;
335                                 mt[1] = m2[1] * pthick * 0.5f;
336                                 sc[0] = s0[0] - (m1[0] * pthick * 0.75f);
337                                 sc[1] = s0[1] - (m1[1] * pthick * 0.75f);
338                                 
339                                 t0[0] = sc[0] - mt[0];
340                                 t0[1] = sc[1] - mt[1];
341                                 t1[0] = sc[0] + mt[0];
342                                 t1[1] = sc[1] + mt[1];
343                                 
344                                 glVertex2fv(t0);
345                                 glVertex2fv(t1);
346                                 
347                                 /* calculate points for start of segment */
348                                 mt[0] = m2[0] * pthick;
349                                 mt[1] = m2[1] * pthick;
350                                 
351                                 t0[0] = s0[0] - mt[0];
352                                 t0[1] = s0[1] - mt[1];
353                                 t1[0] = s0[0] + mt[0];
354                                 t1[1] = s0[1] + mt[1];
355                                 
356                                 /* draw this line twice (first to finish off start cap, then for stroke) */
357                                 glVertex2fv(t1);
358                                 glVertex2fv(t0);
359                                 glVertex2fv(t0);
360                                 glVertex2fv(t1);
361                         }
362                         /* if not the first segment, use bisector of angle between segments */
363                         else {
364                                 float mb[2];         /* bisector normal */
365                                 float athick, dfac;  /* actual thickness, difference between thicknesses */
366                                 
367                                 /* calculate gradient of bisector (as average of normals) */
368                                 mb[0] = (pm[0] + m2[0]) / 2;
369                                 mb[1] = (pm[1] + m2[1]) / 2;
370                                 normalize_v2(mb);
371                                 
372                                 /* calculate gradient to apply 
373                                  *  - as basis, use just pthick * bisector gradient
374                                  *      - if cross-section not as thick as it should be, add extra padding to fix it
375                                  */
376                                 mt[0] = mb[0] * pthick;
377                                 mt[1] = mb[1] * pthick;
378                                 athick = len_v2(mt);
379                                 dfac = pthick - (athick * 2);
380                                 
381                                 if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) {
382                                         mt[0] += (mb[0] * dfac);
383                                         mt[1] += (mb[1] * dfac);
384                                 }       
385                                 
386                                 /* calculate points for start of segment */
387                                 t0[0] = s0[0] - mt[0];
388                                 t0[1] = s0[1] - mt[1];
389                                 t1[0] = s0[0] + mt[0];
390                                 t1[1] = s0[1] + mt[1];
391                                 
392                                 /* draw this line twice (once for end of current segment, and once for start of next) */
393                                 glVertex2fv(t1);
394                                 glVertex2fv(t0);
395                                 glVertex2fv(t0);
396                                 glVertex2fv(t1);
397                         }
398                         
399                         /* if last segment, also draw end of segment (defined as segment's normal) */
400                         if (i == totpoints - 2) {
401                                 /* for once, we use second point's pressure (otherwise it won't be drawn) */
402                                 pthick = (pt2->pressure * thickness);
403                                 
404                                 /* calculate points for end of segment */
405                                 mt[0] = m2[0] * pthick;
406                                 mt[1] = m2[1] * pthick;
407                                 
408                                 t0[0] = s1[0] - mt[0];
409                                 t0[1] = s1[1] - mt[1];
410                                 t1[0] = s1[0] + mt[0];
411                                 t1[1] = s1[1] + mt[1];
412                                 
413                                 /* draw this line twice (once for end of stroke, and once for endcap)*/
414                                 glVertex2fv(t1);
415                                 glVertex2fv(t0);
416                                 glVertex2fv(t0);
417                                 glVertex2fv(t1);
418                                 
419                                 
420                                 /* draw end cap as last step 
421                                  *      - make points slightly closer to center (about halfway across) 
422                                  */                             
423                                 mt[0] = m2[0] * pthick * 0.5f;
424                                 mt[1] = m2[1] * pthick * 0.5f;
425                                 sc[0] = s1[0] + (m1[0] * pthick * 0.75f);
426                                 sc[1] = s1[1] + (m1[1] * pthick * 0.75f);
427                                 
428                                 t0[0] = sc[0] - mt[0];
429                                 t0[1] = sc[1] - mt[1];
430                                 t1[0] = sc[0] + mt[0];
431                                 t1[1] = sc[1] + mt[1];
432                                 
433                                 glVertex2fv(t1);
434                                 glVertex2fv(t0);
435                         }
436                         
437                         /* store stroke's 'natural' normal for next stroke to use */
438                         copy_v2_v2(pm, m2);
439                 }
440                 
441                 glEnd();
442         }
443         
444         /* draw debug points of curve on top? (original stroke points) */
445         if (debug) {
446                 bGPDspoint *pt;
447                 int i;
448                 
449                 glBegin(GL_POINTS);
450                 for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
451                         if (sflag & GP_STROKE_2DSPACE) {
452                                 glVertex2fv(&pt->x);
453                         }
454                         else if (sflag & GP_STROKE_2DIMAGE) {
455                                 const float x = (float)((pt->x * winx) + offsx);
456                                 const float y = (float)((pt->y * winy) + offsy);
457                                 
458                                 glVertex2f(x, y);
459                         }
460                         else {
461                                 const float x = (float)(pt->x / 100 * winx) + offsx;
462                                 const float y = (float)(pt->y / 100 * winy) + offsy;
463                                 
464                                 glVertex2f(x, y);
465                         }
466                 }
467                 glEnd();
468         }
469 }
470
471 /* ----- General Drawing ------ */
472
473 /* draw a set of strokes */
474 static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
475                             short debug, short lthick, float color[4])
476 {
477         bGPDstroke *gps;
478         
479         /* set color first (may need to reset it again later too) */
480         glColor4fv(color);
481         
482         for (gps = gpf->strokes.first; gps; gps = gps->next) {
483                 /* check if stroke can be drawn - checks here generally fall into pairs */
484                 if ((dflag & GP_DRAWDATA_ONLY3D) && !(gps->flag & GP_STROKE_3DSPACE))
485                         continue;
486                 if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
487                         continue;
488                 if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
489                         continue;
490                 if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
491                         continue;
492                 if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
493                         continue;
494                 if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
495                         continue;
496                 if ((gps->points == NULL) || (gps->totpoints < 1))
497                         continue;
498                 
499                 /* check which stroke-drawer to use */
500                 if (gps->totpoints == 1)
501                         gp_draw_stroke_point(gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy);
502                 else if (dflag & GP_DRAWDATA_ONLY3D) {
503                         const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
504                         int mask_orig = 0;
505                         
506                         if (no_xray) {
507                                 glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
508                                 glDepthMask(0);
509                                 glEnable(GL_DEPTH_TEST);
510                                 
511                                 /* first arg is normally rv3d->dist, but this isn't available here and seems to work quite well without */
512                                 bglPolygonOffset(1.0f, 1.0f);
513 #if 0
514                                 glEnable(GL_POLYGON_OFFSET_LINE);
515                                 glPolygonOffset(-1.0f, -1.0f);
516 #endif
517                         }
518                         
519                         gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, debug);
520                         
521                         if (no_xray) {
522                                 glDepthMask(mask_orig);
523                                 glDisable(GL_DEPTH_TEST);
524                                 
525                                 bglPolygonOffset(0.0, 0.0);
526 #if 0
527                                 glDisable(GL_POLYGON_OFFSET_LINE);
528                                 glPolygonOffset(0, 0);
529 #endif
530                         }
531                 }
532                 else if (gps->totpoints > 1)    
533                         gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy);
534         }
535 }
536
537 /* draw grease-pencil datablock */
538 static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
539 {
540         bGPDlayer *gpl;
541         
542         /* reset line drawing style (in case previous user didn't reset) */
543         setlinestyle(0);
544         
545         /* turn on smooth lines (i.e. anti-aliasing) */
546         glEnable(GL_LINE_SMOOTH);
547         
548         /* turn on alpha-blending */
549         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
550         glEnable(GL_BLEND);
551                 
552         /* loop over layers, drawing them */
553         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
554                 bGPDframe *gpf;
555                 
556                 short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0;
557                 short lthick = gpl->thickness;
558                 float color[4], tcolor[4];
559                 
560                 /* don't draw layer if hidden */
561                 if (gpl->flag & GP_LAYER_HIDE) 
562                         continue;
563                 
564                 /* get frame to draw */
565                 gpf = gpencil_layer_getframe(gpl, cfra, 0);
566                 if (gpf == NULL) 
567                         continue;
568                 
569                 /* set color, stroke thickness, and point size */
570                 glLineWidth(lthick);
571                 copy_v4_v4(color, gpl->color); // just for copying 4 array elements
572                 copy_v4_v4(tcolor, gpl->color); // additional copy of color (for ghosting)
573                 glColor4fv(color);
574                 glPointSize((float)(gpl->thickness + 2));
575                 
576                 /* apply xray layer setting */
577                 if (gpl->flag & GP_LAYER_NO_XRAY) dflag |=  GP_DRAWDATA_NO_XRAY;
578                 else dflag &= ~GP_DRAWDATA_NO_XRAY;
579                 
580                 /* draw 'onionskins' (frame left + right) */
581                 if (gpl->flag & GP_LAYER_ONIONSKIN) {
582                         /* drawing method - only immediately surrounding (gstep = 0), or within a frame range on either side (gstep > 0)*/                      
583                         if (gpl->gstep) {
584                                 bGPDframe *gf;
585                                 float fac;
586                                 
587                                 /* draw previous frames first */
588                                 for (gf = gpf->prev; gf; gf = gf->prev) {
589                                         /* check if frame is drawable */
590                                         if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
591                                                 /* alpha decreases with distance from curframe index */
592                                                 fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
593                                                 tcolor[3] = color[3] * fac * 0.66f;
594                                                 gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
595                                         }
596                                         else 
597                                                 break;
598                                 }
599                                 
600                                 /* now draw next frames */
601                                 for (gf = gpf->next; gf; gf = gf->next) {
602                                         /* check if frame is drawable */
603                                         if ((gf->framenum - gpf->framenum) <= gpl->gstep) {
604                                                 /* alpha decreases with distance from curframe index */
605                                                 fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep + 1));
606                                                 tcolor[3] = color[3] * fac * 0.66f;
607                                                 gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
608                                         }
609                                         else 
610                                                 break;
611                                 }       
612                                 
613                                 /* restore alpha */
614                                 glColor4fv(color);
615                         }
616                         else {
617                                 /* draw the strokes for the ghost frames (at half of the alpha set by user) */
618                                 if (gpf->prev) {
619                                         tcolor[3] = (color[3] / 7);
620                                         gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
621                                 }
622                                 
623                                 if (gpf->next) {
624                                         tcolor[3] = (color[3] / 4);
625                                         gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
626                                 }
627                                 
628                                 /* restore alpha */
629                                 glColor4fv(color);
630                         }
631                 }
632                 
633                 /* draw the strokes already in active frame */
634                 tcolor[3] = color[3];
635                 gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
636                 
637                 /* Check if may need to draw the active stroke cache, only if this layer is the active layer
638                  * that is being edited. (Stroke buffer is currently stored in gp-data)
639                  */
640                 if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
641                     (gpf->flag & GP_FRAME_PAINT))
642                 {
643                         /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */
644                         gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
645                 }
646         }
647         
648         /* turn off alpha blending, then smooth lines */
649         glDisable(GL_BLEND); // alpha blending
650         glDisable(GL_LINE_SMOOTH); // smooth lines
651                 
652         /* restore initial gl conditions */
653         glLineWidth(1.0);
654         glPointSize(1.0);
655         glColor4f(0, 0, 0, 1);
656 }
657
658 /* ----- Grease Pencil Sketches Drawing API ------ */
659
660 // ............................
661 // XXX 
662 //      We need to review the calls below, since they may be/are not that suitable for
663 //      the new ways that we intend to be drawing data...
664 // ............................
665
666 /* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */
667 void draw_gpencil_2dimage(const bContext *C)
668 {
669         ScrArea *sa = CTX_wm_area(C);
670         ARegion *ar = CTX_wm_region(C);
671         Scene *scene = CTX_data_scene(C);
672         bGPdata *gpd;
673         int offsx, offsy, sizex, sizey;
674         int dflag = GP_DRAWDATA_NOSTATUS;
675         
676         gpd = gpencil_data_get_active(C); // XXX
677         if (gpd == NULL) return;
678         
679         /* calculate rect */
680         switch (sa->spacetype) {
681                 case SPACE_IMAGE: /* image */
682                 case SPACE_CLIP: /* clip */
683                 {
684                         
685                         /* just draw using standard scaling (settings here are currently ignored anyways) */
686                         // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled
687                         offsx = 0;
688                         offsy = 0;
689                         sizex = ar->winx;
690                         sizey = ar->winy;
691                         
692                         wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
693                         
694                         dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK;
695                 }
696                 break;
697                 case SPACE_SEQ: /* sequence */
698                 {
699                         /* just draw using standard scaling (settings here are currently ignored anyways) */
700                         offsx = 0;
701                         offsy = 0;
702                         sizex = ar->winx;
703                         sizey = ar->winy;
704                         
705                         /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated 
706                          * and everything moved to standard View2d 
707                          */
708                         dflag |= GP_DRAWDATA_ONLYV2D;
709                 }
710                 break;
711                 default: /* for spacetype not yet handled */
712                         offsx = 0;
713                         offsy = 0;
714                         sizex = ar->winx;
715                         sizey = ar->winy;
716                         
717                         dflag |= GP_DRAWDATA_ONLYI2D;
718                         break;
719         }
720         
721         
722         /* draw it! */
723         gp_draw_data(gpd, offsx, offsy, sizex, sizey, CFRA, dflag);
724 }
725
726 /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly 
727  * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, second time with onlyv2d=0 for screen-aligned strokes
728  */
729 void draw_gpencil_view2d(const bContext *C, short onlyv2d)
730 {
731         ScrArea *sa = CTX_wm_area(C);
732         ARegion *ar = CTX_wm_region(C);
733         Scene *scene = CTX_data_scene(C);
734         bGPdata *gpd;
735         int dflag = 0;
736         
737         /* check that we have grease-pencil stuff to draw */
738         if (sa == NULL) return;
739         gpd = gpencil_data_get_active(C); // XXX
740         if (gpd == NULL) return;
741         
742         /* special hack for Image Editor */
743         // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled
744         if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP))
745                 dflag |= GP_DRAWDATA_IEDITHACK;
746         
747         /* draw it! */
748         if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
749         gp_draw_data(gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag);
750 }
751
752 /* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly 
753  * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes, second time with only3d=0 for screen-aligned strokes
754  */
755
756 void draw_gpencil_view3d(Scene *scene, View3D *v3d, ARegion *ar, short only3d)
757 {
758         bGPdata *gpd;
759         int dflag = 0;
760         rcti rect;
761         RegionView3D *rv3d = ar->regiondata;
762
763         /* check that we have grease-pencil stuff to draw */
764         gpd = gpencil_data_get_active_v3d(scene); // XXX
765         if (gpd == NULL) return;
766
767         /* when rendering to the offscreen buffer we don't want to
768          * deal with the camera border, otherwise map the coords to the camera border. */
769         if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) {
770                 rctf rectf;
771                 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, TRUE); /* no shift */
772                 BLI_copy_rcti_rctf(&rect, &rectf);
773         }
774         else {
775                 rect.xmin = 0;
776                 rect.ymin = 0;
777                 rect.xmax = ar->winx;
778                 rect.ymax = ar->winy;
779         }
780         
781         /* draw it! */
782         if (only3d) dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
783
784         gp_draw_data(gpd, rect.xmin, rect.ymin, rect.xmax, rect.ymax, CFRA, dflag);
785 }
786
787 /* ************************************************** */