Grease Pencil - Stick to View for Sequencer:
[blender.git] / source / blender / src / drawseq.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) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <string.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BMF_Api.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_arithb.h"
43
44 #include "IMB_imbuf_types.h"
45
46 #include "DNA_gpencil_types.h"
47 #include "DNA_sequence_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_screen_types.h"
50 #include "DNA_space_types.h"
51 #include "DNA_view2d_types.h"
52 #include "DNA_userdef_types.h"
53
54 #include "BKE_global.h"
55 #include "BKE_plugin_types.h"
56 #include "BKE_scene.h"
57 #include "BKE_utildefines.h"
58  
59 #include "BIF_cursors.h"
60 #include "BIF_gl.h"
61 #include "BIF_graphics.h"
62 #include "BIF_mywindow.h"
63 #include "BIF_screen.h"
64 #include "BIF_drawseq.h"
65 #include "BIF_editseq.h"
66 #include "BIF_glutil.h"
67 #include "BIF_resources.h"
68 #include "BIF_space.h"
69 #include "BIF_interface.h"
70
71 #include "BIF_drawgpencil.h"
72 #include "BDR_gpencil.h"
73
74 #include "BSE_view.h"
75 #include "BSE_drawipo.h"
76 #include "BSE_sequence.h"
77 #include "BSE_seqeffects.h"
78 #include "BSE_seqscopes.h"
79 #include "BSE_seqaudio.h"
80 #include "BSE_time.h"
81
82 #include "IMB_imbuf_types.h"
83 #include "IMB_imbuf.h"
84
85 #include "blendef.h"    /* CFRA */
86 #include "mydevice.h"   /* REDRAWSEQ */
87 #include "interface.h"
88 #include "winlay.h"
89
90 #define SEQ_LEFTHANDLE          1
91 #define SEQ_RIGHTHANDLE 2
92
93 #define SEQ_STRIP_OFSBOTTOM             0.2
94 #define SEQ_STRIP_OFSTOP                0.8
95
96 /* Note, Dont use WHILE_SEQ while drawing! - it messes up transform, - Campbell */
97
98 int no_rightbox=0, no_leftbox= 0;
99 static void draw_seq_handle(Sequence *seq, SpaceSeq *sseq, float pixelx, short direction);
100 static void draw_seq_extensions(Sequence *seq, SpaceSeq *sseq);
101 static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2, char *background_col);
102 static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2);
103 static void draw_seq_strip(struct Sequence *seq, struct ScrArea *sa, struct SpaceSeq *sseq, int outline_tint, float pixelx);
104
105
106 static void seq_panel_gpencil(short cntrl)      // SEQ_HANDLER_GREASEPENCIL
107 {
108         uiBlock *block;
109         SpaceSeq *sseq;
110         
111         sseq= curarea->spacedata.first;
112
113         block= uiNewBlock(&curarea->uiblocks, "seq_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win);
114         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
115         uiSetPanelHandler(SEQ_HANDLER_GREASEPENCIL);  // for close and esc
116         if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceSeq", 100, 30, 318, 204)==0) return;
117         
118         /* only draw settings if right mode */
119         if (sseq->mainb == 0)
120                 return;
121         
122         /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
123         if (sseq->flag & SEQ_DRAW_GPENCIL) {
124                 if (sseq->gpd == NULL)
125                         gpencil_data_setactive(curarea, gpencil_data_addnew());
126         }
127         
128         if (sseq->flag & SEQ_DRAW_GPENCIL) {
129                 bGPdata *gpd= sseq->gpd;
130                 short newheight;
131                 
132                 /* this is a variable height panel, newpanel doesnt force new size on existing panels */
133                 /* so first we make it default height */
134                 uiNewPanelHeight(block, 204);
135                 
136                 /* draw button for showing gpencil settings and drawings */
137                 uiDefButBitI(block, TOG, SEQ_DRAW_GPENCIL, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sseq->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Sequencer View (draw using Shift-LMB)");
138                 
139                 /* extend the panel if the contents won't fit */
140                 newheight= draw_gpencil_panel(block, gpd, curarea); 
141                 uiNewPanelHeight(block, newheight);
142         }
143         else {
144                 uiDefButBitI(block, TOG, SEQ_DRAW_GPENCIL, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sseq->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Sequencer View");
145                 uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
146         }
147 }
148
149 static void seq_blockhandlers(ScrArea *sa)
150 {
151         SpaceSeq *sseq= sa->spacedata.first;
152         short a;
153
154         /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */
155         uiFreeBlocksWin(&sa->uiblocks, sa->win);
156
157         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
158                 switch(sseq->blockhandler[a]) {
159                         case SEQ_HANDLER_GREASEPENCIL:
160                                 seq_panel_gpencil(sseq->blockhandler[a+1]);
161                                 break;
162                 }
163         }
164         uiDrawBlocksPanels(sa, 0);
165
166 }
167
168
169 static void draw_cfra_seq(void)
170 {
171         glColor3ub(0x30, 0x90, 0x50);
172         glLineWidth(2.0);
173         glBegin(GL_LINES);
174         glVertex2f(G.scene->r.cfra, G.v2d->cur.ymin);
175         glVertex2f(G.scene->r.cfra, G.v2d->cur.ymax);
176         glEnd();
177         glLineWidth(1.0);
178 }
179
180 static void get_seq_color3ubv(Sequence *seq, char *col)
181 {
182         char blendcol[3];
183         float hsv[3], rgb[3];
184         SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
185
186         switch(seq->type) {
187         case SEQ_IMAGE:
188                 BIF_GetThemeColor3ubv(TH_SEQ_IMAGE, col);
189                 break;
190         case SEQ_META:
191                 BIF_GetThemeColor3ubv(TH_SEQ_META, col);
192                 break;
193         case SEQ_MOVIE:
194                 BIF_GetThemeColor3ubv(TH_SEQ_MOVIE, col);
195                 break;
196         case SEQ_SCENE:
197                 BIF_GetThemeColor3ubv(TH_SEQ_SCENE, col);
198                 
199                 if(seq->scene==G.scene) {
200                         BIF_GetColorPtrBlendShade3ubv(col, col, col, 1.0, 20);
201                 }
202                 break;
203
204         /* transitions */
205         case SEQ_CROSS:
206         case SEQ_GAMCROSS:
207         case SEQ_WIPE:
208                 /* slightly offset hue to distinguish different effects */
209                 BIF_GetThemeColor3ubv(TH_SEQ_TRANSITION, col);
210                 
211                 rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0; 
212                 rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
213                 
214                 if (seq->type == SEQ_CROSS)             hsv[0]+= 0.04;
215                 if (seq->type == SEQ_GAMCROSS)  hsv[0]+= 0.08;
216                 if (seq->type == SEQ_WIPE)              hsv[0]+= 0.12;
217                 
218                 if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
219                 hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
220                 col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255); 
221                 break;
222                 
223         /* effects */
224         case SEQ_TRANSFORM:
225         case SEQ_SPEED:
226         case SEQ_ADD:
227         case SEQ_SUB:
228         case SEQ_MUL:
229         case SEQ_ALPHAOVER:
230         case SEQ_ALPHAUNDER:
231         case SEQ_OVERDROP:
232         case SEQ_GLOW:
233                 /* slightly offset hue to distinguish different effects */
234                 BIF_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
235                 
236                 rgb[0] = col[0]/255.0; rgb[1] = col[1]/255.0; rgb[2] = col[2]/255.0; 
237                 rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
238                 
239                 if (seq->type == SEQ_ADD)               hsv[0]+= 0.04;
240                 if (seq->type == SEQ_SUB)               hsv[0]+= 0.08;
241                 if (seq->type == SEQ_MUL)               hsv[0]+= 0.12;
242                 if (seq->type == SEQ_ALPHAOVER) hsv[0]+= 0.16;
243                 if (seq->type == SEQ_ALPHAUNDER)        hsv[0]+= 0.20;
244                 if (seq->type == SEQ_OVERDROP)  hsv[0]+= 0.24;
245                 if (seq->type == SEQ_GLOW)              hsv[0]+= 0.28;
246                 if (seq->type == SEQ_TRANSFORM)         hsv[0]+= 0.36;
247
248                 if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
249                 hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
250                 col[0] = (char)(rgb[0]*255); col[1] = (char)(rgb[1]*255); col[2] = (char)(rgb[2]*255); 
251                 break;
252         case SEQ_COLOR:
253                 if (colvars->col) {
254                         col[0]= (char)(colvars->col[0]*255);
255                         col[1]= (char)(colvars->col[1]*255);
256                         col[2]= (char)(colvars->col[2]*255);
257                 } else {
258                         col[0] = col[1] = col[2] = 128;
259                 }
260                 break;
261         case SEQ_PLUGIN:
262                 BIF_GetThemeColor3ubv(TH_SEQ_PLUGIN, col);
263                 break;
264         case SEQ_HD_SOUND:
265         case SEQ_RAM_SOUND:
266                 BIF_GetThemeColor3ubv(TH_SEQ_AUDIO, col);
267                 blendcol[0] = blendcol[1] = blendcol[2] = 128;
268                 if(seq->flag & SEQ_MUTE) BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20);
269                 break;
270         default:
271                 col[0] = 10; col[1] = 255; col[2] = 40;
272         }
273 }
274
275 static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, float y2)
276 {
277         /* Note, this used to use WHILE_SEQ, but it messes up the seq->depth value, (needed by transform when doing overlap checks)
278          * so for now, just use the meta's immediate children, could be fixed but its only drawing - Campbell */
279         Sequence *seq;
280         float dx;
281         int nr;
282         char col[3];
283         
284         nr= BLI_countlist(&seqm->seqbase);
285
286         dx= (x2-x1)/nr;
287
288         if (seqm->flag & SEQ_MUTE) {
289                 glEnable(GL_POLYGON_STIPPLE);
290                 glPolygonStipple(stipple_halftone);
291                 
292                 glEnable(GL_LINE_STIPPLE);
293                 glLineStipple(1, 0x8888);
294         }
295         
296         for (seq= seqm->seqbase.first; seq; seq= seq->next) {
297                 get_seq_color3ubv(seq, col);
298                 
299                 glColor3ubv((GLubyte *)col);
300
301                 glRectf(x1,  y1,  x1+0.9*dx,  y2);
302                 
303                 BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -30);
304                 glColor3ubv((GLubyte *)col);
305
306                 fdrawbox(x1,  y1,  x1+0.9*dx,  y2);
307                 
308                 x1+= dx;
309         }
310         
311         if (seqm->flag & SEQ_MUTE) {
312                 glDisable(GL_POLYGON_STIPPLE);
313                 glDisable(GL_LINE_STIPPLE);
314         }
315 }
316
317 static void drawseqwave(Sequence *seq, float x1, float y1, float x2, float y2, int winx)
318 {
319         /*
320         x1 is the starting x value to draw the wave,
321         x2 the end x value, same for y1 and y2
322         winx is the zoom level.
323         */
324         
325         float
326         f, /* floating point value used to store the X draw location for the wave lines when openGL drawing*/
327         midy, /* fast access to the middle location (y1+y2)/2 */
328         clipxmin, /* the minimum X value, clip this with the window */
329         clipxmax, /* the maximum X value, clip this with the window */
330         sample_step, /* steps to move per sample, floating value must later translate into an int */
331         fsofs, /* steps to move per sample, floating value must later translate into an int */
332         feofs_sofs, /*  */
333         sound_width, /* convenience: x2-x1 */
334         wavemulti; /* scale the samples by this value when GL_LINE drawing so it renders the right height */
335         
336         int
337         offset, /* initial offset value for the wave drawing */
338         offset_next, /* when in the wave drawing loop this value is the samples intil the next vert */
339         sofs, /* Constrained offset value (~3) for the wave, start */
340         eofs, /* ditto, end */
341         wavesample, /* inner loop storage if the current wave sample value, used to make the 2 values below */
342         wavesamplemin, /* used for finding the min and max wave peaks */
343         wavesamplemax, /* ditto */
344         subsample_step=4; /* when the sample step is 4 every sample of
345         the wave is evaluated for min and max values used to draw the wave,
346         however this is slow ehrn zoomed out so when the sample step is above
347         1 (the larger the further out the zoom is) so not evaluate all samples, only some. */
348         
349         signed short* s;
350         bSound *sound;
351         Uint8 *stream;
352         
353         audio_makestream(seq->sound);
354         if(seq->sound==NULL || seq->sound->stream==NULL) return;
355         
356         if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0);
357         
358         sofs = ((int)( FRA2TIME(seq->startdisp-seq->start+seq->anim_startofs)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
359         eofs = ((int)( FRA2TIME(seq->enddisp-seq->start+seq->anim_startofs)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
360         
361         /* clip the drawing area to the screen bounds to save time */
362         sample_step= (G.v2d->cur.xmax - G.v2d->cur.xmin)/winx;
363         clipxmin= MAX2(x1, G.v2d->cur.xmin);
364         clipxmax= MIN2(x2, G.v2d->cur.xmax);
365         
366         if (sample_step > 1)
367                 subsample_step= ((int)(subsample_step*sample_step*8)) & (~3);
368         
369         /* for speedy access */
370         midy = (y1+y2)/2;
371         fsofs= (float)sofs;
372         feofs_sofs= (float)(eofs-sofs);
373         sound_width= x2-x1;
374         sound = seq->sound;
375         stream = sound->stream;
376         wavemulti = (y2-y1)/196605; /*y2-y1 is the height*/
377         wavesample=0;
378         
379         /* we need to get the starting offset value, excuse the duplicate code */
380         f=clipxmin;
381         offset= (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
382         
383         /* start the loop, draw a line per sample_step -sample_step is about 1 line drawn per pixel */
384         glBegin(GL_LINES);
385         for (f=x1+sample_step; f<=clipxmax; f+=sample_step) {
386                 
387                 offset_next = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
388                 if (f > G.v2d->cur.xmin) {
389                         /* if this is close to the last sample just exit */
390                         if (offset_next >= sound->streamlen) break;
391                         
392                         wavesamplemin = 131070;
393                         wavesamplemax = -131070;
394                         
395                         /*find with high and low of the waveform for this draw,
396                         evaluate small samples to find this range */
397                         while (offset < offset_next) {
398                                 s = (signed short*)(stream+offset);
399                                 
400                                 wavesample = s[0]*2 + s[1];
401                                 if (wavesamplemin>wavesample)
402                                         wavesamplemin=wavesample;
403                                 if (wavesamplemax<wavesample)
404                                         wavesamplemax=wavesample;
405                                 offset+=subsample_step;
406                         }
407                         /* draw the wave line, looks good up close and zoomed out */
408                         glVertex2f(f,  midy-(wavemulti*wavesamplemin) );
409                         glVertex2f(f,  midy-(wavemulti*wavesamplemax) );
410                 } else {
411                         while (offset < offset_next) offset+=subsample_step;
412                 }
413                 
414                 offset=offset_next;
415         }
416         glEnd();
417 }
418
419 /* draw a handle, for each end of a sequence strip */
420 static void draw_seq_handle(Sequence *seq, SpaceSeq *sseq, float pixelx, short direction)
421 {
422         float v1[2], v2[2], v3[2], rx1=0, rx2=0; //for triangles and rect
423         float x1, x2, y1, y2;
424         float handsize;
425         float minhandle, maxhandle;
426         char str[32];
427         unsigned int whichsel=0;
428         View2D *v2d;
429         
430         x1= seq->startdisp;
431         x2= seq->enddisp;
432         
433         y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
434         y2= seq->machine+SEQ_STRIP_OFSTOP;
435         
436         v2d = &sseq->v2d;
437         
438         /* clamp handles to defined size in pixel space */
439         handsize = seq->handsize;
440         minhandle = 7;
441         maxhandle = 40;
442         CLAMP(handsize, minhandle*pixelx, maxhandle*pixelx);
443         
444         /* set up co-ordinates/dimensions for either left or right handle */
445         if (direction == SEQ_LEFTHANDLE) {      
446                 rx1 = x1;
447                 rx2 = x1+handsize*0.75;
448                 
449                 v1[0]= x1+handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
450                 v2[0]= x1+handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
451                 v3[0]= v2[0] + handsize/4; v3[1]= (y1+y2)/2.0;
452                 
453                 whichsel = SEQ_LEFTSEL;
454         } else if (direction == SEQ_RIGHTHANDLE) {      
455                 rx1 = x2-handsize*0.75;
456                 rx2 = x2;
457                 
458                 v1[0]= x2-handsize/4; v1[1]= y1+( ((y1+y2)/2.0 - y1)/2);
459                 v2[0]= x2-handsize/4; v2[1]= y2-( ((y1+y2)/2.0 - y1)/2);
460                 v3[0]= v2[0] - handsize/4; v3[1]= (y1+y2)/2.0;
461                 
462                 whichsel = SEQ_RIGHTSEL;
463         }
464         
465         /* draw! */
466         if(seq->type < SEQ_EFFECT || 
467            get_sequence_effect_num_inputs(seq->type) == 0) {
468                 glEnable( GL_BLEND );
469                 
470                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
471                 
472                 if(seq->flag & whichsel) glColor4ub(0, 0, 0, 80);
473                 else if (seq->flag & SELECT) glColor4ub(255, 255, 255, 30);
474                 else glColor4ub(0, 0, 0, 22);
475                 
476                 glRectf(rx1, y1, rx2, y2);
477                 
478                 if(seq->flag & whichsel) glColor4ub(255, 255, 255, 200);
479                 else glColor4ub(0, 0, 0, 50);
480                 
481                 glEnable( GL_POLYGON_SMOOTH );
482                 glBegin(GL_TRIANGLES);
483                 glVertex2fv(v1); glVertex2fv(v2); glVertex2fv(v3);
484                 glEnd();
485                 
486                 glDisable( GL_POLYGON_SMOOTH );
487                 glDisable( GL_BLEND );
488         }
489         
490         if(G.moving || (seq->flag & whichsel)) {
491                 cpack(0xFFFFFF);
492                 if (direction == SEQ_LEFTHANDLE) {
493                         sprintf(str, "%d", seq->startdisp);
494                         glRasterPos3f(rx1,  y1-0.15, 0.0);
495                 } else {
496                         sprintf(str, "%d", seq->enddisp - 1);
497                         glRasterPos3f((x2-BMF_GetStringWidth(G.fonts, str)*pixelx),  y2+0.05, 0.0);
498                 }
499                 BMF_DrawString(G.fonts, str);
500         }       
501 }
502
503 static void draw_seq_extensions(Sequence *seq, SpaceSeq *sseq)
504 {
505         float x1, x2, y1, y2, pixely, a;
506         char col[3], blendcol[3];
507         View2D *v2d;
508         
509         if(seq->type >= SEQ_EFFECT) return;
510
511         x1= seq->startdisp;
512         x2= seq->enddisp;
513         
514         y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
515         y2= seq->machine+SEQ_STRIP_OFSTOP;
516         
517         v2d = &sseq->v2d;
518         pixely = (v2d->cur.ymax - v2d->cur.ymin)/(v2d->mask.ymax - v2d->mask.ymin);
519         
520         blendcol[0] = blendcol[1] = blendcol[2] = 120;
521
522         if(seq->startofs) {
523                 glEnable( GL_BLEND );
524                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
525                 
526                 get_seq_color3ubv(seq, col);
527                 
528                 if (seq->flag & SELECT) {
529                         BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
530                         glColor4ub(col[0], col[1], col[2], 170);
531                 } else {
532                         BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
533                         glColor4ub(col[0], col[1], col[2], 110);
534                 }
535                 
536                 glRectf((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1);
537                 
538                 if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
539                 else glColor4ub(col[0], col[1], col[2], 160);
540
541                 fdrawbox((float)(seq->start), y1-SEQ_STRIP_OFSBOTTOM, x1, y1);  //outline
542                 
543                 glDisable( GL_BLEND );
544         }
545         if(seq->endofs) {
546                 glEnable( GL_BLEND );
547                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
548                 
549                 get_seq_color3ubv(seq, col);
550                 
551                 if (seq->flag & SELECT) {
552                         BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
553                         glColor4ub(col[0], col[1], col[2], 170);
554                 } else {
555                         BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
556                         glColor4ub(col[0], col[1], col[2], 110);
557                 }
558                 
559                 glRectf(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM);
560                 
561                 if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
562                 else glColor4ub(col[0], col[1], col[2], 160);
563
564                 fdrawbox(x2, y2, (float)(seq->start+seq->len), y2+SEQ_STRIP_OFSBOTTOM); //outline
565                 
566                 glDisable( GL_BLEND );
567         }
568         if(seq->startstill) {
569                 get_seq_color3ubv(seq, col);
570                 BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
571                 glColor3ubv((GLubyte *)col);
572                 
573                 draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
574                 
575                 /* feint pinstripes, helps see exactly which is extended and which isn't,
576                 * especially when the extension is very small */ 
577                 if (seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
578                 else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
579                 
580                 glColor3ubv((GLubyte *)col);
581                 
582                 for(a=y1; a< y2; a+= pixely*2.0 ) {
583                         fdrawline(x1,  a,  (float)(seq->start),  a);
584                 }
585         }
586         if(seq->endstill) {
587                 get_seq_color3ubv(seq, col);
588                 BIF_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
589                 glColor3ubv((GLubyte *)col);
590                 
591                 draw_shadedstrip(seq, col, (float)(seq->start+seq->len), y1, x2, y2);
592                 
593                 /* feint pinstripes, helps see exactly which is extended and which isn't,
594                 * especially when the extension is very small */ 
595                 if (seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
596                 else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -16);
597                 
598                 glColor3ubv((GLubyte *)col);
599                 
600                 for(a=y1; a< y2; a+= pixely*2.0 ) {
601                         fdrawline((float)(seq->start+seq->len),  a,  x2,  a);
602                 }
603         }
604 }
605
606 /* draw info text on a sequence strip */
607 static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2, char *background_col)
608 {
609         float v1[2], v2[2];
610         int len, size;
611         char str[32 + FILE_MAXDIR+FILE_MAXFILE], *strp;
612         short mval[2];
613         
614         v1[1]= y1;
615         v2[1]= y2;
616         
617         v1[0]= x1;
618         ipoco_to_areaco_noclip(G.v2d, v1, mval);
619         x1= mval[0];
620         v2[0]= x2;
621         ipoco_to_areaco_noclip(G.v2d, v2, mval);
622         x2= mval[0];
623         size= x2-x1;
624         
625         if(seq->name[2]) {
626                 sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->name+2);
627         }else{
628                 if(seq->type == SEQ_META) {
629                         sprintf(str, "%d | %s", seq->len, give_seqname(seq));
630                 }
631                 else if(seq->type == SEQ_SCENE) {
632                         if(seq->scene) sprintf(str, "%d | %s: %s", seq->len, give_seqname(seq), seq->scene->id.name+2);
633                         else sprintf(str, "%d | %s", seq->len, give_seqname(seq));
634                         
635                 }
636                 else if(seq->type == SEQ_IMAGE) {
637                         sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
638                 }
639                 else if(seq->type & SEQ_EFFECT) {
640                         int can_float = (seq->type != SEQ_PLUGIN)
641                                 || (seq->plugin && seq->plugin->version >= 4);
642
643                         if(seq->seq3!=seq->seq2 && seq->seq1!=seq->seq3)
644                                 sprintf(str, "%d | %s: %d>%d (use %d)%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, seq->seq3->machine, can_float ? "" : " No float, upgrade plugin!");
645                         else if (seq->seq1 && seq->seq2)
646                                 sprintf(str, "%d | %s: %d>%d%s", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, can_float ? "" : " No float, upgrade plugin!");
647                         else 
648                                 sprintf(str, "%d | %s", seq->len, give_seqname(seq));
649                 }
650                 else if (seq->type == SEQ_RAM_SOUND) {
651                         sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
652                 }
653                 else if (seq->type == SEQ_HD_SOUND) {
654                         sprintf(str, "%d | %s", seq->len, seq->strip->stripdata->name);
655                 }
656                 else if (seq->type == SEQ_MOVIE) {
657                         sprintf(str, "%d | %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
658                 }
659         }
660         
661         strp= str;
662         
663         while( (len= BMF_GetStringWidth(G.font, strp)) > size) {
664                 if(len < 10) break;
665                 if(strp[1]==0) break;
666                 strp++;
667         }
668         
669         mval[0]= (x1+x2-len+1)/2;
670         mval[1]= 1;
671         areamouseco_to_ipoco(G.v2d, mval, &x1, &x2);
672         
673         if(seq->flag & SELECT){
674                 cpack(0xFFFFFF);
675         }else if ((((int)background_col[0] + (int)background_col[1] + (int)background_col[2]) / 3) < 50){
676                 cpack(0x505050); /* use lighter text colour for dark background */
677         }else{
678                 cpack(0);
679         }
680         glRasterPos3f(x1,  y1+SEQ_STRIP_OFSBOTTOM, 0.0);
681         BMF_DrawString(G.font, strp);
682 }
683
684 /* draws a shaded strip, made from gradient + flat color + gradient */
685 static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2)
686 {
687         float ymid1, ymid2;
688         
689         if (seq->flag & SEQ_MUTE) {
690                 glEnable(GL_POLYGON_STIPPLE);
691                 glPolygonStipple(stipple_halftone);
692         }
693         
694         ymid1 = (y2-y1)*0.25 + y1;
695         ymid2 = (y2-y1)*0.65 + y1;
696         
697         glShadeModel(GL_SMOOTH);
698         glBegin(GL_QUADS);
699         
700         if(seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -50);
701         else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 0);
702         
703         glColor3ubv((GLubyte *)col);
704         
705         glVertex2f(x1,y1);
706         glVertex2f(x2,y1);
707         
708         if(seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5);
709         else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -5);
710
711         glColor3ubv((GLubyte *)col);
712         
713         glVertex2f(x2,ymid1);
714         glVertex2f(x1,ymid1);
715         
716         glEnd();
717         
718         glRectf(x1,  ymid1,  x2,  ymid2);
719         
720         glBegin(GL_QUADS);
721         
722         glVertex2f(x1,ymid2);
723         glVertex2f(x2,ymid2);
724         
725         if(seq->flag & SELECT) BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -15);
726         else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 25);
727         
728         glColor3ubv((GLubyte *)col);
729         
730         glVertex2f(x2,y2);
731         glVertex2f(x1,y2);
732         
733         glEnd();
734         
735         if (seq->flag & SEQ_MUTE) {
736                 glDisable(GL_POLYGON_STIPPLE);
737         }
738 }
739
740 /*
741 Draw a sequence strip, bounds check alredy made
742 ScrArea is currently only used to get the windows width in pixels
743 so wave file sample drawing precission is zoom adjusted
744 */
745 static void draw_seq_strip(Sequence *seq, ScrArea *sa, SpaceSeq *sseq, int outline_tint, float pixelx)
746 {
747         float x1, x2, y1, y2;
748         char col[3], background_col[3], is_single_image;
749
750         /* we need to know if this is a single image/color or not for drawing */
751         is_single_image = (char)check_single_seq(seq);
752         
753         /* body */
754         if(seq->startstill) x1= seq->start;
755         else x1= seq->startdisp;
756         y1= seq->machine+SEQ_STRIP_OFSBOTTOM;
757         if(seq->endstill) x2= seq->start+seq->len;
758         else x2= seq->enddisp;
759         y2= seq->machine+SEQ_STRIP_OFSTOP;
760         
761         
762         /* get the correct color per strip type*/
763         //get_seq_color3ubv(seq, col);
764         get_seq_color3ubv(seq, background_col);
765         
766         /* draw the main strip body */
767         if (is_single_image) /* single image */
768                 draw_shadedstrip(seq, background_col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2);
769         else /* normal operation */
770                 draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
771         
772         /* draw additional info and controls */
773         if (seq->type == SEQ_RAM_SOUND)
774                 drawseqwave(seq, x1, y1, x2, y2, sa->winx);
775         
776         if (!is_single_image)
777                 draw_seq_extensions(seq, sseq);
778         
779         draw_seq_handle(seq, sseq, pixelx, SEQ_LEFTHANDLE);
780         draw_seq_handle(seq, sseq, pixelx, SEQ_RIGHTHANDLE);
781         
782         /* draw the strip outline */
783         x1= seq->startdisp;
784         x2= seq->enddisp;
785         
786         get_seq_color3ubv(seq, col);
787         if (G.moving && (seq->flag & SELECT)) {
788                 if(seq->flag & SEQ_OVERLAP) {
789                         col[0]= 255; col[1]= col[2]= 40;
790                 } else BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 120);
791         }
792
793         BIF_GetColorPtrBlendShade3ubv(col, col, col, 0.0, outline_tint);
794         
795         glColor3ubv((GLubyte *)col);
796         
797         if (seq->flag & SEQ_MUTE) {
798                 glEnable(GL_LINE_STIPPLE);
799                 glLineStipple(1, 0x8888);
800         }
801         
802         gl_round_box_shade(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
803         
804         if (seq->flag & SEQ_MUTE) {
805                 glDisable(GL_LINE_STIPPLE);
806         }
807         
808         /* calculate if seq is long enough to print a name */
809         x1= seq->startdisp+seq->handsize;
810         x2= seq->enddisp-seq->handsize;
811
812         /* but first the contents of a meta */
813         if(seq->type==SEQ_META) drawmeta_contents(seq, x1, y1+0.15, x2, y2-0.15);
814
815         /* info text on the strip */
816         if(x1<G.v2d->cur.xmin) x1= G.v2d->cur.xmin;
817         else if(x1>G.v2d->cur.xmax) x1= G.v2d->cur.xmax;
818         if(x2<G.v2d->cur.xmin) x2= G.v2d->cur.xmin;
819         else if(x2>G.v2d->cur.xmax) x2= G.v2d->cur.xmax;
820
821         /* nice text here would require changing the view matrix for texture text */
822         if( (x2-x1) / pixelx > 32) {
823                 draw_seq_text(seq, x1, x2, y1, y2, background_col);
824         }
825 }
826
827 static Sequence *special_seq_update= 0;
828
829 void set_special_seq_update(int val)
830 {
831         int x;
832
833         /* if mouse over a sequence && LEFTMOUSE */
834         if(val) {
835                 special_seq_update= find_nearest_seq(&x);
836         }
837         else special_seq_update= 0;
838 }
839
840
841 static void draw_image_seq(ScrArea *sa)
842 {
843         SpaceSeq *sseq;
844         struct ImBuf *ibuf;
845         int x1, y1, rectx, recty;
846         int free_ibuf = 0;
847         static int recursive= 0;
848         float zoom;
849         float zoomx, zoomy;
850
851         glClearColor(0.0, 0.0, 0.0, 0.0);
852         glClear(GL_COLOR_BUFFER_BIT);
853
854         sseq= sa->spacedata.first;
855         if(sseq==0) return;
856
857         rectx= (G.scene->r.size*G.scene->r.xsch)/100;
858         recty= (G.scene->r.size*G.scene->r.ysch)/100;
859
860         /* BIG PROBLEM: the give_ibuf_seq() can call a rendering, which in turn calls redraws...
861            this shouldn't belong in a window drawing....
862            So: solve this once event based. 
863            Now we check for recursion, space type and active area again (ton) */
864         
865         if(recursive)
866                 return;
867         else {
868                 recursive= 1;
869                 if (special_seq_update) {
870                         ibuf= give_ibuf_seq_direct(
871                                 rectx, recty, (G.scene->r.cfra),
872                                 special_seq_update);
873                 } else if (!U.prefetchframes || (G.f & G_PLAYANIM) == 0) {
874                         ibuf= (ImBuf *)give_ibuf_seq(
875                                 rectx, recty, (G.scene->r.cfra), 
876                                 sseq->chanshown);
877                 } else {
878                         ibuf= (ImBuf *)give_ibuf_seq_threaded(
879                                 rectx, recty, (G.scene->r.cfra), 
880                                 sseq->chanshown);
881                 }
882                 recursive= 0;
883                 
884                 /* HURMF! the give_ibuf_seq can call image display in this window */
885                 if(sa->spacetype!=SPACE_SEQ)
886                         return;
887                 if(sa!=curarea) {
888                         areawinset(sa->win);
889                 }
890         }
891         
892         if(ibuf==NULL) 
893                 return;
894
895         if(ibuf->rect==NULL && ibuf->rect_float == NULL) 
896                 return;
897
898         switch(sseq->mainb) {
899         case SEQ_DRAW_IMG_IMBUF:
900                 if (sseq->zebra != 0) {
901                         ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
902                         free_ibuf = 1;
903                 }
904                 break;
905         case SEQ_DRAW_IMG_WAVEFORM:
906                 if ((sseq->flag & SEQ_DRAW_COLOR_SEPERATED) != 0) {
907                         ibuf = make_sep_waveform_view_from_ibuf(ibuf);
908                 } else {
909                         ibuf = make_waveform_view_from_ibuf(ibuf);
910                 }
911                 free_ibuf = 1;
912                 break;
913         case SEQ_DRAW_IMG_VECTORSCOPE:
914                 ibuf = make_vectorscope_view_from_ibuf(ibuf);
915                 free_ibuf = 1;
916                 break;
917         case SEQ_DRAW_IMG_HISTOGRAM:
918                 ibuf = make_histogram_view_from_ibuf(ibuf);
919                 free_ibuf = 1;
920                 break;
921         }
922
923         if(ibuf->rect_float && ibuf->rect==NULL)
924                 IMB_rect_from_float(ibuf);
925         
926         /* needed for gla draw */
927         glaDefine2DArea(&curarea->winrct);
928         
929         zoom= SEQ_ZOOM_FAC(sseq->zoom);
930         if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
931                 zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp);
932                 zoomy = zoom;
933         } else {
934                 zoomx = zoomy = zoom;
935         }
936
937         /* calc location */
938         x1= (sa->winx-zoomx*ibuf->x)/2 + sseq->xof;
939         y1= (sa->winy-zoomy*ibuf->y)/2 + sseq->yof;
940         
941         glPixelZoom(zoomx, zoomy);
942         
943         glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
944         
945         glPixelZoom(1.0, 1.0);
946
947         /* safety border */
948         if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && 
949             (sseq->flag & SEQ_DRAW_SAFE_MARGINS) != 0) {
950                 float fac= 0.1;
951                 float x2 = x1 + ibuf->x * zoomx;
952                 float y2 = y1 + ibuf->y * zoomy;
953                 
954                 float a= fac*(x2-x1);
955                 x1+= a; 
956                 x2-= a;
957         
958                 a= fac*(y2-y1);
959                 y1+= a;
960                 y2-= a;
961         
962                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
963                 setlinestyle(3);
964
965                 BIF_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
966                 
967                 uiSetRoundBox(15);
968                 gl_round_box(GL_LINE_LOOP, x1, y1, x2, y2, 12.0);
969
970                 setlinestyle(0);
971                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
972         }
973         
974         /* draw grease-pencil (image aligned) */
975         if (sseq->flag & SEQ_DRAW_GPENCIL)
976                 draw_gpencil_2dimage(sa, ibuf);
977
978         if (free_ibuf) {
979                 IMB_freeImBuf(ibuf);
980         } 
981         
982         /* draw grease-pencil (screen aligned) */
983         if (sseq->flag & SEQ_DRAW_GPENCIL)
984                 draw_gpencil_2dview(sa, 0);
985         
986         /* ortho at pixel level sa */
987         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
988         
989         /* it is important to end a view in a transform compatible with buttons */
990         bwin_scalematrix(sa->win, sseq->blockscale, sseq->blockscale, sseq->blockscale);
991         seq_blockhandlers(sa);
992
993         sa->win_swap= WIN_BACK_OK;
994 }
995
996 void seq_reset_imageofs(SpaceSeq *sseq)
997 {
998         sseq->xof = sseq->yof = sseq->zoom = 0;
999 }
1000
1001 void seq_home(void)
1002 {
1003         SpaceSeq *sseq= curarea->spacedata.first;
1004         
1005         if (!sseq->mainb) {
1006                 G.v2d->cur= G.v2d->tot;
1007                 test_view2d(G.v2d, curarea->winx, curarea->winy);
1008                 view2d_do_locks(curarea, V2D_LOCK_COPY);
1009         } else {
1010                 float zoomX, zoomY;
1011                 int width, height, imgwidth, imgheight; 
1012                 
1013                 width = curarea->winx;
1014                 height = curarea->winy;
1015                 
1016                 seq_reset_imageofs(sseq);
1017                 
1018                 imgwidth= (G.scene->r.size*G.scene->r.xsch)/100;
1019                 imgheight= (G.scene->r.size*G.scene->r.ysch)/100;
1020                 
1021                 /* Apply aspect, dosnt need to be that accurate */
1022                 imgwidth= (int)(imgwidth * ((float)G.scene->r.xasp / (float)G.scene->r.yasp));
1023                 
1024                 if (((imgwidth >= width) || (imgheight >= height)) && 
1025                         ((width > 0) && (height > 0))) {
1026                         
1027                         /* Find the zoom value that will fit the image in the image space */
1028                         zoomX = ((float)width) / ((float)imgwidth);
1029                         zoomY = ((float)height) / ((float)imgheight);
1030                         sseq->zoom= (zoomX < zoomY) ? zoomX : zoomY;
1031         
1032                         sseq->zoom = 1.0f / power_of_2(1/ MIN2(zoomX, zoomY) );
1033                 }
1034                 else {
1035                         sseq->zoom= 1.0f;
1036                 }
1037         }
1038         scrarea_queue_winredraw(curarea);
1039 }
1040
1041 void seq_viewzoom(unsigned short event, int invert)
1042 {
1043         SpaceSeq *sseq= curarea->spacedata.first;
1044
1045         if(event==PAD1)
1046                 sseq->zoom= 1.0;
1047         else if(event==PAD2)
1048                 sseq->zoom= (invert)? 2.0: 0.5;
1049         else if(event==PAD4)
1050                 sseq->zoom= (invert)? 4.0: 0.25;
1051         else if(event==PAD8)
1052                 sseq->zoom= (invert)? 8.0: 0.125;
1053         
1054         /* ensure pixel exact locations for draw */
1055         sseq->xof= (int)sseq->xof;
1056         sseq->yof= (int)sseq->yof;
1057 }
1058
1059 void seq_viewmove(SpaceSeq *sseq)
1060 {       
1061         ScrArea *sa;
1062         short mval[2], mvalo[2];
1063         short rectx, recty, xmin, xmax, ymin, ymax, pad;
1064         int oldcursor;
1065         Window *win;
1066         
1067         sa = sseq->area;
1068         rectx= (G.scene->r.size*G.scene->r.xsch)/100;
1069         recty= (G.scene->r.size*G.scene->r.ysch)/100;
1070         
1071         pad = 10;
1072         xmin = -(sa->winx/2) - rectx/2 + pad;
1073         xmax = sa->winx/2 + rectx/2 - pad;
1074         ymin = -(sa->winy/2) - recty/2 + pad;
1075         ymax = sa->winy/2 + recty/2 - pad;
1076         
1077         getmouseco_sc(mvalo);
1078
1079         oldcursor=get_cursor();
1080         win=winlay_get_active_window();
1081         
1082         SetBlenderCursor(BC_NSEW_SCROLLCURSOR);
1083         
1084         while(get_mbut()&(L_MOUSE|M_MOUSE)) {
1085                 
1086                 getmouseco_sc(mval);
1087                 
1088                 if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
1089
1090                         sseq->xof -= (mvalo[0]-mval[0]);
1091                         sseq->yof -= (mvalo[1]-mval[1]);
1092                         
1093                         /* prevent dragging image outside of the window and losing it! */
1094                         CLAMP(sseq->xof, xmin, xmax);
1095                         CLAMP(sseq->yof, ymin, ymax);
1096                         
1097                         mvalo[0]= mval[0];
1098                         mvalo[1]= mval[1];
1099                         
1100                         scrarea_do_windraw(curarea);
1101                         screen_swapbuffers();
1102                 }
1103                 else BIF_wait_for_statechange();
1104         }
1105         window_set_cursor(win, oldcursor);
1106 }
1107
1108 void drawprefetchseqspace(ScrArea *sa, void *spacedata)
1109 {
1110         SpaceSeq *sseq= sa->spacedata.first;
1111         int rectx, recty;
1112
1113         rectx= (G.scene->r.size*G.scene->r.xsch)/100;
1114         recty= (G.scene->r.size*G.scene->r.ysch)/100;
1115
1116         if(sseq->mainb) {
1117                 give_ibuf_prefetch_request(
1118                         rectx, recty, (G.scene->r.cfra), sseq->chanshown);
1119         }
1120 }
1121
1122 void drawseqspace(ScrArea *sa, void *spacedata)
1123 {
1124         SpaceSeq *sseq= sa->spacedata.first;
1125         View2D *v2d= &sseq->v2d;
1126         Editing *ed;
1127         Sequence *seq;
1128         float col[3];
1129         int ofsx, ofsy;
1130         int i;
1131
1132         ed= G.scene->ed;
1133
1134         if(sseq->mainb) {
1135                 draw_image_seq(sa);
1136                 return;
1137         }
1138
1139         bwin_clear_viewmat(sa->win);    /* clear buttons view */
1140         glLoadIdentity();
1141
1142         BIF_GetThemeColor3fv(TH_BACK, col);
1143         if(ed && ed->metastack.first) glClearColor(col[0], col[1], col[2]-0.1, 0.0);
1144         else glClearColor(col[0], col[1], col[2], 0.0);
1145
1146         glClear(GL_COLOR_BUFFER_BIT);
1147
1148         calc_scrollrcts(sa, v2d, sa->winx, sa->winy);
1149
1150         if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
1151                 if(v2d->scroll) {
1152                         ofsx= sa->winrct.xmin;  /* because of mywin */
1153                         ofsy= sa->winrct.ymin;
1154                         glViewport(ofsx+v2d->mask.xmin,  ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
1155                         glScissor(ofsx+v2d->mask.xmin,  ofsy+v2d->mask.ymin, ( ofsx+v2d->mask.xmax-1)-(ofsx+v2d->mask.xmin)+1, ( ofsy+v2d->mask.ymax-1)-( ofsy+v2d->mask.ymin)+1);
1156                 }
1157         }
1158
1159
1160         myortho2(v2d->cur.xmin, v2d->cur.xmax, v2d->cur.ymin, v2d->cur.ymax);
1161
1162         BIF_ThemeColorShade(TH_BACK, -20);
1163         glRectf(v2d->cur.xmin,  0.0,  v2d->cur.xmax,  1.0);
1164
1165         
1166         boundbox_seq();
1167         calc_ipogrid();
1168         
1169         /* Alternating horizontal stripes */
1170         i= MAX2(1, ((int)G.v2d->cur.ymin)-1);
1171
1172         glBegin(GL_QUADS);
1173         while (i<v2d->cur.ymax) {
1174                 if (((int)i) & 1)
1175                         BIF_ThemeColorShade(TH_BACK, -15);
1176                 else
1177                         BIF_ThemeColorShade(TH_BACK, -25);
1178                 
1179                 glVertex2f(v2d->cur.xmax, i);
1180                 glVertex2f(v2d->cur.xmin, i);
1181                 glVertex2f(v2d->cur.xmin, i+1);
1182                 glVertex2f(v2d->cur.xmax, i+1);
1183                 i+=1.0;
1184         }
1185         glEnd();
1186         
1187         /* Force grid lines */
1188         i= MAX2(1, ((int)G.v2d->cur.ymin)-1);
1189         glBegin(GL_LINES);
1190
1191         while (i<G.v2d->cur.ymax) {
1192                 BIF_ThemeColor(TH_GRID);
1193                 glVertex2f(G.v2d->cur.xmax, i);
1194                 glVertex2f(G.v2d->cur.xmin, i);
1195                 i+=1.0;
1196         }
1197         glEnd();
1198         
1199         
1200         draw_ipogrid();
1201         draw_cfra_seq();
1202
1203
1204         /* sequences: first deselect */
1205         if(ed) {
1206                 Sequence *last_seq = get_last_seq();
1207                 int sel = 0, j;
1208                 int outline_tint;
1209                 float pixelx = (v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin);
1210                 /* loop through twice, first unselected, then selected */
1211                 for (j=0; j<2; j++) {
1212                         seq= ed->seqbasep->first;
1213                         if (j==0)       outline_tint = -150;
1214                         else            outline_tint = -60;
1215                         
1216                         while(seq) { /* bound box test, dont draw outside the view */
1217                                 if (  ((seq->flag & SELECT) == sel) ||
1218                                                 seq == last_seq ||
1219                                                 MIN2(seq->startdisp, seq->start) > v2d->cur.xmax ||
1220                                                 MAX2(seq->enddisp, seq->start+seq->len) < v2d->cur.xmin ||
1221                                                 seq->machine+1.0 < v2d->cur.ymin ||
1222                                                 seq->machine > v2d->cur.ymax)
1223                                 {
1224                                         /* dont draw */
1225                                 } else {
1226                                         draw_seq_strip(seq, sa, sseq, outline_tint, pixelx);
1227                                 }
1228                                 seq= seq->next;
1229                         }
1230                         sel= SELECT; /* draw selected next time round */
1231                 }
1232                 /* draw the last selected last, removes some overlapping error */
1233                 if (last_seq) {
1234                         draw_seq_strip(last_seq, sa, sseq, 120, pixelx);
1235                 }
1236         }
1237
1238         /* Draw markers */
1239         draw_markers_timespace(SCE_MARKERS, DRAW_MARKERS_LINES);
1240         
1241         /* restore viewport */
1242         mywinset(sa->win);
1243
1244         /* ortho at pixel level sa */
1245         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
1246
1247         if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
1248                 if(v2d->scroll) {
1249                         drawscroll(0);
1250                 }
1251         }
1252
1253         draw_area_emboss(sa);
1254
1255         if(sseq->mainb==0) {
1256                 /* it is important to end a view in a transform compatible with buttons */
1257                 bwin_scalematrix(sa->win, sseq->blockscale, sseq->blockscale, sseq->blockscale);
1258                 seq_blockhandlers(sa);
1259         }
1260
1261         sa->win_swap= WIN_BACK_OK;
1262 }
1263
1264