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