reduced dithering on sequence wave redraw.
[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
55 #include "BKE_global.h"
56 #include "BKE_plugin_types.h"
57 #include "BKE_scene.h"
58 #include "BKE_utildefines.h"
59
60 #include "BIF_gl.h"
61 #include "BIF_mywindow.h"
62 #include "BIF_screen.h"
63 #include "BIF_drawseq.h"
64 #include "BIF_editseq.h"
65 #include "BIF_glutil.h"
66 #include "BIF_resources.h"
67 #include "BIF_space.h"
68 #include "BIF_interface.h"
69
70 #include "BSE_view.h"
71 #include "BSE_drawipo.h"
72 #include "BSE_sequence.h"
73 #include "BSE_seqaudio.h"
74
75 #include "IMB_imbuf_types.h"
76 #include "IMB_imbuf.h"
77
78 #include "blendef.h"    /* CFRA */
79 #include "mydevice.h"   /* REDRAWSEQ */
80
81 int no_rightbox=0, no_leftbox= 0;
82
83 static void EmbossBoxf(float x1, float y1, float x2, float y2, int sel, unsigned int dark, unsigned int light)
84 {
85
86         if(sel) cpack(dark);
87         else cpack(light);
88         if(sel) glLineWidth(2.0);
89         fdrawline(x1,  y2,  x2,  y2);   /* top */
90         if(no_leftbox==0) fdrawline(x1,  y1,  x1,  y2); /* left */
91
92         if(sel) glLineWidth(1.0);
93
94         if(sel) cpack(light);
95         else cpack(dark);
96         fdrawline(x1,  y1,  x2,  y1); /* bottom */
97         if(no_rightbox==0) fdrawline(x2,  y1,  x2,  y2);        /* right */
98
99 }
100
101 static char *give_seqname(Sequence *seq)
102 {
103         if(seq->type==SEQ_META) {
104                 if(seq->name[2]) return seq->name+2;
105                 return "META";
106         }
107         else if(seq->type==SEQ_IMAGE) return "IMAGE";
108         else if(seq->type==SEQ_SCENE) return "SCENE";
109         else if(seq->type==SEQ_MOVIE) return "MOVIE";
110         else if(seq->type==SEQ_SOUND) return "AUDIO";
111         else if(seq->type<SEQ_EFFECT) return seq->strip->dir;
112         else if(seq->type==SEQ_CROSS) return "CROSS";
113         else if(seq->type==SEQ_GAMCROSS) return "GAMMA CROSS";
114         else if(seq->type==SEQ_ADD) return "ADD";
115         else if(seq->type==SEQ_SUB) return "SUB";
116         else if(seq->type==SEQ_MUL) return "MUL";
117         else if(seq->type==SEQ_ALPHAOVER) return "ALPHAOVER";
118         else if(seq->type==SEQ_ALPHAUNDER) return "ALPHAUNDER";
119         else if(seq->type==SEQ_OVERDROP) return "OVER DROP";
120         else if(seq->type==SEQ_WIPE) return "WIPE";
121         else if(seq->type==SEQ_GLOW) return "GLOW";
122         else if(seq->type==SEQ_PLUGIN) {
123                 if(seq->plugin && seq->plugin->doit) return seq->plugin->pname;
124                 return "PLUGIN";
125         }
126         else return "EFFECT";
127
128 }
129 static void draw_cfra_seq(void)
130 {
131         glColor3ub(0x30, 0x90, 0x50);
132         glLineWidth(2.0);
133         glBegin(GL_LINES);
134         glVertex2f(G.scene->r.cfra, G.v2d->cur.ymin);
135         glVertex2f(G.scene->r.cfra, G.v2d->cur.ymax);
136         glEnd();
137         glLineWidth(1.0);
138 }
139
140 static unsigned int seq_color(Sequence *seq)
141 {
142         switch(seq->type) {
143         case SEQ_META:
144                 return 0x509090;
145         case SEQ_MOVIE:
146                 return 0x805040;
147         case SEQ_SCENE:
148                 if(seq->scene==G.scene) return 0x709050;
149                 return 0x609060;
150         case SEQ_CROSS:
151                 return 0x505090;
152         case SEQ_GAMCROSS:
153                 return 0x5040A0;
154         case SEQ_ADD:
155                 return 0x6060A0;
156         case SEQ_SUB:
157                 return 0x8060A0;
158         case SEQ_MUL:
159                 return 0x8080A0;
160         case SEQ_ALPHAOVER:
161                 return 0x6080A0;
162         case SEQ_ALPHAUNDER:
163                 return 0x9080A0;
164         case SEQ_OVERDROP:
165                 return 0x5080B0;
166         case SEQ_WIPE:
167                 return 0x2080B0;
168         case SEQ_GLOW:
169                 return 0x0080B0;
170         case SEQ_PLUGIN:
171                 return 0x906000;
172         case SEQ_SOUND:
173                 if(seq->flag & SEQ_MUTE) return 0x707060; else return 0x787850;
174         default:
175                 return 0x906060;
176         }
177
178 }
179 static void drawmeta_contents(Sequence *seqm, float x1, float y1, float x2, float y2)
180 {
181         Sequence *seq;
182         float dx;
183         int nr;
184
185         nr= 0;
186         WHILE_SEQ(&seqm->seqbase) {
187                 nr++;
188         }
189         END_SEQ
190
191         dx= (x2-x1)/nr;
192
193         WHILE_SEQ(&seqm->seqbase) {
194                 cpack(seq_color(seq));
195                 glRectf(x1,  y1,  x1+0.9*dx,  y2);
196                 EmbossBoxf(x1, y1, x1+0.9*dx, y2, 0, 0x404040, 0xB0B0B0);
197                 x1+= dx;
198         }
199         END_SEQ
200 }
201
202 static void drawseqwave(Sequence *seq, float x1, float y1, float x2, float y2, int winx)
203 {
204         float f, height, midy, clipxmin, clipxmax, sample_step;
205         int offset, offset_next, sofs, eofs, i=0;
206         signed short* s;
207         bSound *sound;
208         int wavesample, wavesamplemin, wavesamplemax, subsample_step=4; /* used for finding the min and max wave peaks */
209         Uint8 *stream;
210         float fsofs, feofs_sofs, sound_width; /* for faster access in the loop */
211         
212         audio_makestream(seq->sound);
213         if(seq->sound->stream==NULL) return;    
214         
215         if (seq->flag & SEQ_MUTE) glColor3ub(0x70, 0x80, 0x80); else glColor3ub(0x70, 0xc0, 0xc0);
216         
217         sofs = ((int)( (((float)(seq->startdisp-seq->start))/(float)G.scene->r.frs_sec)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
218         eofs = ((int)( (((float)(seq->enddisp-seq->start))/(float)G.scene->r.frs_sec)*(float)G.scene->audio.mixrate*4.0 )) & (~3);
219         
220         /* clip the drawing area to the screen bounds to save time */
221         sample_step= (G.v2d->cur.xmax-G.v2d->cur.xmin)/winx;
222         clipxmin= MAX2(x1, G.v2d->cur.xmin);
223         clipxmax= MIN2(x2, G.v2d->cur.xmax);
224         
225         /* Stops dithering on redraw when clipxmin is offset. */
226         if (clipxmin != x1) {
227                 clipxmin = (float) ((int)((clipxmin*sample_step)+(i*sample_step))) / sample_step;
228                 while (clipxmin < x1) {
229                         clipxmin = (float) ((int)((clipxmin*sample_step)+(i*sample_step))) / sample_step;
230                         i+=1;
231                 }
232                 clipxmin = (float)((int)clipxmin); /* snap to int */    
233         }
234         
235         /* when the sample step is 4 every sample of the wave is evaluated for min and max
236         values used to draw the wave, however this is slow ehrn zoomed out
237         so when the sample step is above 1 (the larger the further out the zoom is)
238         so not evaluate all samples, only some.*/
239         if (sample_step > 1)
240                 subsample_step= ((int)(subsample_step*sample_step*8)) & (~3);
241         
242         /* for speedy access */
243         midy = (y1+y2)/2;
244         fsofs= (float)sofs;
245         feofs_sofs= (float)(eofs-sofs);
246         sound_width= x2-x1;
247         height= y2-y1;
248         sound = seq->sound;
249         stream = sound->stream;
250         wavesample=0;
251         
252         /* we need to get the starting offset value, excuse the duplicate code */
253         f=clipxmin;
254         offset = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
255         
256         /* start the loop, draw a line per sample_step -sample_step is about 1 line drawn per pixel */
257         glBegin(GL_LINES);
258         for (f=clipxmin+sample_step; f<=clipxmax; f+=sample_step) {
259                 
260                 offset_next = (int) (fsofs + ((f-x1)/sound_width) * feofs_sofs) & (~3);
261                 
262                 /* if this is close to the last sample just exit */
263                 if (offset_next >= sound->streamlen) break;
264                 
265                 wavesamplemin = 655360;
266                 wavesamplemax = -655360;
267                 
268                 /*find with high and low of the waveform for this draw,
269                 evaluate small samples to find this range */
270                 while (offset <= offset_next) {
271                         s = (signed short*)(stream+offset);
272                         
273                         wavesample = s[0] + s[1]/2;
274                         if (wavesamplemin>wavesample)
275                                 wavesamplemin=wavesample;
276                         if (wavesamplemax<wavesample)
277                                 wavesamplemax=wavesample;
278                         offset+=subsample_step;
279                 }
280                 /* draw the wave line, looks good up close and zoomed out */
281                 glVertex2f(f,  midy-(((((float)wavesamplemin)/65536)* height)/2) );
282                 glVertex2f(f,  midy-(((((float)wavesamplemax)/65536)* height)/2) );
283                 offset=offset_next;
284         }
285         glEnd();
286 }
287
288 /*
289 Draw a sequencer block, bounds check alredy made
290 ScrArea is currently only used to get the windows width in pixels
291 so wave file sample drawing precission is zoom adjusted
292 */
293 void drawseq(Sequence *seq, ScrArea *sa)
294 {
295         float v1[2], v2[2], x1, x2, y1, y2, color_tint[4];
296         unsigned int body, dark, light;
297         int len, size;
298         short mval[2];
299         char str[120], *strp;
300
301
302         if(seq->startdisp > seq->enddisp) body= 0x707070;
303
304         body= seq_color(seq);
305         dark= 0x202020;
306         light= 0xB0B0B0;
307
308         if(G.moving && (seq->flag & SELECT)) {
309                 if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
310                 else {
311                         if(seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL));
312                         else dark= light= 0xFFFFFF;
313                 }
314         }
315
316         /* body */
317         if(seq->startstill) x1= seq->start;
318         else x1= seq->startdisp;
319         y1= seq->machine+0.2;
320         if(seq->endstill) x2= seq->start+seq->len;
321         else x2= seq->enddisp;
322         y2= seq->machine+0.8;
323
324         cpack(body);
325         glRectf(x1,  y1,  x2,  y2);
326         if (seq->type == SEQ_SOUND) drawseqwave(seq, x1, y1, x2, y2, sa->winx);
327         EmbossBoxf(x1, y1, x2, y2, seq->flag & 1, dark, light);
328
329         v1[1]= y1;
330         v2[1]= y2;
331         if(seq->type < SEQ_EFFECT) {
332
333                 /* decoration: the bars */
334                 x1= seq->startdisp;
335                 x2= seq->enddisp;
336
337                 if(seq->startofs) {
338                         cpack(0x707070);
339                         glRectf((float)(seq->start),  y1-0.2,  x1,  y1);
340                         EmbossBoxf((float)(seq->start), y1-0.2, x1, y1, seq->flag & 1, dark, light);
341                 }
342                 if(seq->endofs) {
343                         cpack(0x707070);
344                         glRectf(x2,  y2,  (float)(seq->start+seq->len),  y2+0.2);
345                         EmbossBoxf(x2, y2, (float)(seq->start+seq->len), y2+0.2, seq->flag & 1, dark, light);
346                 }
347
348                 if(seq->startstill) {
349                         cpack(body);
350                         glRectf(x1,  y1+0.1,  (float)(seq->start),  y1+0.5);
351                         no_rightbox= 1;
352                         EmbossBoxf(x1, y1+0.1, (float)(seq->start), y1+0.5, seq->flag & 1, dark, light);
353                         no_rightbox= 0;
354                 }
355                 if(seq->endstill) {
356                         cpack(body);
357                         glRectf((float)(seq->start+seq->len),  y1+0.1,  x2,  y1+0.5);
358                         no_leftbox= 1;
359                         EmbossBoxf((float)(seq->start+seq->len), y1+0.1, x2, y1+0.5, seq->flag & 1, dark, light);
360                         no_leftbox= 0;
361                 }
362
363         }
364
365         /* calculate if seq is long enough to print a name */
366         x1= seq->startdisp+seq->handsize;
367         x2= seq->enddisp-seq->handsize;
368
369         /* but first the contents of a meta */
370         if(seq->type==SEQ_META) drawmeta_contents(seq, x1, y1+0.15, x2, y2-0.15);
371
372         if(x1<G.v2d->cur.xmin) x1= G.v2d->cur.xmin;
373         else if(x1>G.v2d->cur.xmax) x1= G.v2d->cur.xmax;
374         if(x2<G.v2d->cur.xmin) x2= G.v2d->cur.xmin;
375         else if(x2>G.v2d->cur.xmax) x2= G.v2d->cur.xmax;
376
377         if(x1 != x2) {
378                 v1[0]= x1;
379                 ipoco_to_areaco_noclip(G.v2d, v1, mval);
380                 x1= mval[0];
381                 v2[0]= x2;
382                 ipoco_to_areaco_noclip(G.v2d, v2, mval);
383                 x2= mval[0];
384                 size= x2-x1;
385
386                 if(seq->name[2]) {
387                         sprintf(str, "%s: %s (%d)", give_seqname(seq), seq->name+2, seq->len);
388                 }else{
389                         if(seq->type == SEQ_META) {
390                                 sprintf(str, "%d %s", seq->len, give_seqname(seq));
391                         }
392                         else if(seq->type == SEQ_SCENE) {
393                                 if(seq->scene) sprintf(str, "%d %s %s", seq->len, give_seqname(seq), seq->scene->id.name+2);
394                                 else sprintf(str, "%d %s", seq->len, give_seqname(seq));
395
396                         }
397                         else if(seq->type == SEQ_IMAGE) {
398                                 sprintf(str, "%d %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
399                         }
400                         else if(seq->type & SEQ_EFFECT) {
401                                 if(seq->seq3!=seq->seq2 && seq->seq1!=seq->seq3)
402                                         sprintf(str, "%d %s: %d-%d (use %d)", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine, seq->seq3->machine);
403                                 else
404                                         sprintf(str, "%d %s: %d-%d", seq->len, give_seqname(seq), seq->seq1->machine, seq->seq2->machine);
405                         }
406                         else if (seq->type == SEQ_SOUND) {
407                                 sprintf(str, "%d %s", seq->len, seq->strip->stripdata->name);
408                         }
409                         else if (seq->type == SEQ_MOVIE) {
410                                 sprintf(str, "%d %s%s", seq->len, seq->strip->dir, seq->strip->stripdata->name);
411                         }
412                 }
413
414
415                 strp= str;
416
417                 while( (len= BMF_GetStringWidth(G.font, strp)) > size) {
418                         if(len < 10) break;
419                         if(strp[1]==0) break;
420                         strp++;
421                 }
422
423                 mval[0]= (x1+x2-len+1)/2;
424                 mval[1]= 1;
425                 areamouseco_to_ipoco(G.v2d, mval, &x1, &x2);
426
427                 if(seq->flag & SELECT) cpack(0xFFFFFF);
428                 else cpack(0x0);
429                 glRasterPos3f(x1,  y1+0.2, 0.0);
430                 BMF_DrawString(G.font, strp);
431         }
432         
433
434         
435         if(seq->type < SEQ_EFFECT) {
436                 /* decoration: triangles */
437                 x1= seq->startdisp;
438                 x2= seq->enddisp;
439
440                 body+= 0x101010;
441                 dark= 0x202020;
442                 light= 0xB0B0B0;
443
444                 /* left triangle */
445                 if(seq->flag & SEQ_LEFTSEL) {
446                         cpack(body+0x20);
447                         if(G.moving) {
448                                 if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
449                                 else dark= light= 0xFFFFFF;
450                         }
451                 } else {
452                         cpack(body);
453                 }
454         
455                 /*Tint the color for wave display to show through */
456                 if (seq->type == SEQ_SOUND) {
457                         glEnable( GL_BLEND );
458                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
459                         glGetFloatv(GL_CURRENT_COLOR, color_tint);
460                         glColor4f(color_tint[0], color_tint[1], color_tint[2], 0.7);
461                 }
462                 
463                 glBegin(GL_TRIANGLES);
464                         v1[0]= x1; glVertex2fv(v1);
465                         v2[0]= x1; glVertex2fv(v2);
466                         v2[0]+= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
467                 glEnd();
468
469                 cpack(light);
470                 glBegin(GL_LINE_STRIP);
471                         v1[0]= x1; glVertex2fv(v1);
472                         v2[0]= x1; glVertex2fv(v2);
473                         v2[0]+= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
474                         cpack(dark);
475                         glVertex2fv(v1);
476                 glEnd();
477         }
478
479
480                 /* right triangle */
481         if(seq->type < SEQ_EFFECT) {
482                 dark= 0x202020;
483                 light= 0xB0B0B0;
484
485                 if(seq->flag & SEQ_RIGHTSEL) {
486                         cpack(body+0x20);
487                         if(G.moving) {
488                                 if(seq->flag & SEQ_OVERLAP) dark= light= 0x4040FF;
489                                 else dark= light= 0xFFFFFF;
490                         }
491                 }
492                 else {
493                         cpack(body);
494                 }
495                 /*Tint the color for wave display to show through */
496                 if (seq->type == SEQ_SOUND) {
497                         glGetFloatv(GL_CURRENT_COLOR, color_tint);
498                         glColor4f(color_tint[0], color_tint[1], color_tint[2], 0.7);
499                 }
500                 
501                 glBegin(GL_TRIANGLES);
502                         v2[0]= x2; glVertex2fv(v2);
503                         v1[0]= x2; glVertex2fv(v1);
504                         v2[0]-= seq->handsize; v2[1]= (y1+y2)/2.0; glVertex2fv(v2); v2[1]= y2;
505                 glEnd();
506                 
507                 if (seq->type == SEQ_SOUND)
508                         glDisable( GL_BLEND );
509
510                 cpack(dark);
511                 glBegin(GL_LINE_STRIP);
512                         v2[0]= x2; glVertex2fv(v2);
513                         v1[0]= x2; glVertex2fv(v1);
514                         v1[0]-= seq->handsize; v1[1]= (y1+y2)/2.0; glVertex2fv(v1); v1[1]= y2;
515                         cpack(light);
516                         glVertex2fv(v2);
517                 glEnd();
518         }
519         
520         
521         if(G.moving || (seq->flag & SEQ_LEFTSEL)) {
522                 cpack(0xFFFFFF);
523                 glRasterPos3f(x1,  y1+0.2, 0.0);
524                 sprintf(str, "%d", seq->startdisp);
525                 BMF_DrawString(G.font, str);
526         }
527         
528         if(G.moving || (seq->flag & SEQ_RIGHTSEL)) {
529                 cpack(0xFFFFFF);
530                 glRasterPos3f(x2-seq->handsize/2,  y1+0.2, 0.0);
531                 sprintf(str, "%d", seq->enddisp-1);
532                 BMF_DrawString(G.font, str);
533         }
534 }
535
536 static Sequence *special_seq_update= 0;
537
538 void set_special_seq_update(int val)
539 {
540         int x;
541
542         /* if mouse over a sequence && LEFTMOUSE */
543         if(val) {
544                 special_seq_update= find_nearest_seq(&x);
545         }
546         else special_seq_update= 0;
547 }
548
549
550 static void draw_image_seq(ScrArea *sa)
551 {
552         SpaceSeq *sseq;
553         StripElem *se;
554         struct ImBuf *ibuf;
555         int x1, y1, rectx, recty;
556         float zoom;
557
558         glClearColor(0.0, 0.0, 0.0, 0.0);
559         glClear(GL_COLOR_BUFFER_BIT);
560         
561         rectx= (G.scene->r.size*G.scene->r.xsch)/100;
562         recty= (G.scene->r.size*G.scene->r.ysch)/100;
563         
564         ibuf= (ImBuf *)give_ibuf_seq(rectx, recty, (G.scene->r.cfra));
565
566         if(special_seq_update) {
567        se = special_seq_update->curelem;
568        if(se) {
569            if(se->ok==2) {
570                if(se->se1)
571                    ibuf= se->se1->ibuf;
572            }
573            else ibuf= se->ibuf;
574        }
575         }
576         if(ibuf==0 || ibuf->rect==0) return;
577
578         sseq= sa->spacedata.first;
579         if(sseq==0) return;
580
581         if (sseq->zoom > 0) zoom = sseq->zoom;
582         else zoom = -1.0/sseq->zoom;
583         /* calc location */
584         x1= (sa->winx-zoom*ibuf->x)/2;
585         y1= (sa->winy-zoom*ibuf->y)/2;
586
587         /* needed for gla draw */
588         glaDefine2DArea(&curarea->winrct);
589         glPixelZoom(zoom, zoom);
590         
591         glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
592         
593         glPixelZoom(1.0, 1.0);
594
595         sa->win_swap= WIN_BACK_OK;
596 }
597
598 static void draw_extra_seqinfo(void)
599 {
600         extern Sequence *last_seq;
601         StripElem *se, *last;
602         float xco, xfac;
603         int sta, end;
604         char str[256];
605
606         if(last_seq==0) return;
607
608         /* xfac: size of 1 pixel */
609         xfac= G.v2d->cur.xmax - G.v2d->cur.xmin;
610         xfac/= (float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
611         xco= G.v2d->cur.xmin+40*xfac;
612
613         BIF_ThemeColor(TH_TEXT);
614
615         /* NAME */
616         glRasterPos3f(xco,  0.3, 0.0);
617         strncpy(str, give_seqname(last_seq), 255);
618         BMF_DrawString(G.font, str);
619         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
620
621         if(last_seq->type==SEQ_SCENE && last_seq->scene) {
622                 glRasterPos3f(xco,  0.3, 0.0);
623                 BMF_DrawString(G.font, last_seq->scene->id.name+2);
624                 xco += xfac*BMF_GetStringWidth(G.font, last_seq->scene->id.name+2) +30.0*xfac;
625         }
626
627         /* LEN */
628         if(last_seq->type & SEQ_EFFECT)
629                 sprintf(str, "len: %d   From %d - %d", last_seq->len, last_seq->startdisp, last_seq->enddisp-1);
630         else
631                 sprintf(str, "len: %d (%d)", last_seq->enddisp-last_seq->startdisp, last_seq->len);
632
633         glRasterPos3f(xco,  0.3, 0.0);
634         BMF_DrawString(G.font, str);
635         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
636
637         if(last_seq->type==SEQ_IMAGE) {
638
639                 /* CURRENT */
640                 se= (StripElem *)give_stripelem(last_seq,  (G.scene->r.cfra));
641                 if(se) {
642                         sprintf(str, "cur: %s", se->name);
643                         glRasterPos3f(xco,  0.3, 0.0);
644                         BMF_DrawString(G.font, str);
645                         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
646                 }
647
648                 /* FIRST AND LAST */
649
650                 if(last_seq->strip) {
651                         se= last_seq->strip->stripdata;
652                         last= se+last_seq->len-1;
653                         if(last_seq->startofs) se+= last_seq->startofs;
654                         if(last_seq->endofs) last-= last_seq->endofs;
655
656                         sprintf(str, "First: %s at %d     Last: %s at %d", se->name, last_seq->startdisp, last->name, last_seq->enddisp-1);
657                         glRasterPos3f(xco,  0.3, 0.0);
658                         BMF_DrawString(G.font, str);
659                         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
660
661                         /* orig size */
662                         sprintf(str, "OrigSize: %d x %d", last_seq->strip->orx, last_seq->strip->ory);
663                         glRasterPos3f(xco,  0.3, 0.0);
664                         BMF_DrawString(G.font, str);
665                         xco += xfac*BMF_GetStringWidth(G.font, str) +30.0*xfac;
666                 }
667         }
668         else if(last_seq->type==SEQ_MOVIE) {
669
670                 sta= last_seq->startofs;
671                 end= last_seq->len-1-last_seq->endofs;
672
673                 sprintf(str, "%s   %s%s  First: %d at %d     Last: %d at %d     Cur: %d",
674                                 last_seq->name+2, last_seq->strip->dir, last_seq->strip->stripdata->name,
675                                 sta, last_seq->startdisp, end, last_seq->enddisp-1,  (G.scene->r.cfra)-last_seq->startdisp);
676
677                 glRasterPos3f(xco,  0.3, 0.0);
678                 BMF_DrawString(G.font, str);
679         }
680         else if(last_seq->type==SEQ_SOUND) {
681
682                 sta= last_seq->startofs;
683                 end= last_seq->len-1-last_seq->endofs;
684
685                 sprintf(str, "%s   %s%s  First: %d at %d     Last: %d at %d     Cur: %d     Gain: %.2f dB     Pan: %.2f",
686                                 last_seq->name+2, last_seq->strip->dir, last_seq->strip->stripdata->name,
687                                 sta, last_seq->startdisp, end, last_seq->enddisp-1,  (G.scene->r.cfra)-last_seq->startdisp,
688                                 last_seq->level, last_seq->pan);
689
690                 glRasterPos3f(xco,  0.3, 0.0);
691                 BMF_DrawString(G.font, str);
692         }
693 }
694
695 #define SEQ_BUT_PLUGIN  1
696 #define SEQ_BUT_RELOAD  2
697 #define SEQ_BUT_EFFECT  3
698
699 void do_seqbuttons(short val)
700 {
701         extern Sequence *last_seq;
702
703         switch(val) {
704         case SEQ_BUT_PLUGIN:
705                 new_stripdata(last_seq);
706                 free_imbuf_effect_spec(CFRA);
707                 break;
708
709         case SEQ_BUT_RELOAD:
710                 free_imbuf_seq();       // frees all
711                 break;
712         case SEQ_BUT_EFFECT:
713                 new_stripdata(last_seq);
714                 calc_sequence(last_seq);
715                 break;
716         }
717
718         allqueue(REDRAWSEQ, 0);
719 }
720
721 static void seq_panel_properties(short cntrl)   // SEQ_HANDLER_PROPERTIES
722 {
723         extern Sequence *last_seq;
724         uiBlock *block;
725
726         block= uiNewBlock(&curarea->uiblocks, "seq_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
727         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
728         uiSetPanelHandler(SEQ_HANDLER_PROPERTIES);  // for close and esc
729         if(uiNewPanel(curarea, block, "Strip Properties", "Seq", 10, 230, 318, 204)==0) return;
730
731         if(last_seq==NULL) return;
732
733         if(last_seq->type==SEQ_PLUGIN) {
734                 PluginSeq *pis;
735                 VarStruct *varstr;
736                 int a, xco, yco;
737
738                 uiDefBut(block, LABEL, 0, "Type: Plugin", 10,50,70,20, 0, 0, 0, 0, 0, "");
739
740                 pis= last_seq->plugin;
741                 if(pis->vars==0) return;
742
743                 varstr= pis->varstr;
744                 if(varstr) {
745                         for(a=0; a<pis->vars; a++, varstr++) {
746                                 xco= 150*(a/6)+10;
747                                 yco= 125 - 20*(a % 6)+1;
748                                 uiDefBut(block, varstr->type, SEQ_BUT_PLUGIN, varstr->name, xco,yco,150,19, &(pis->data[a]), varstr->min, varstr->max, 100, 0, varstr->tip);
749
750                         }
751                 }
752         }
753         else if(last_seq->type==SEQ_IMAGE) {
754
755                 uiDefBut(block, LABEL, 0, "Type: Image", 10,140,150,20, 0, 0, 0, 0, 0, "");
756                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
757
758                 uiDefButBitS(block, TOG, SEQ_MAKE_PREMUL, SEQ_BUT_RELOAD, "Convert to Premul", 10,90,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Converts RGB values to become premultiplied with Alpha");
759                 uiDefButBitS(block, TOG, SEQ_FILTERY, SEQ_BUT_RELOAD, "FilterY",        10,70,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "For video movies to remove fields");
760                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Mul:",                   10,50,150,19, &last_seq->mul, 0.001, 5.0, 100, 0, "Multiply colors");
761                 uiDefButS(block, TOG|BIT|7, SEQ_BUT_RELOAD, "Reverse Frames", 10,30,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Reverse frame order");
762                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Strobe:",                        10,10,150,19, &last_seq->strobe, 1.0, 30.0, 100, 0, "Only display every nth frame");
763         }
764         else if(last_seq->type==SEQ_META) {
765
766                 uiDefBut(block, LABEL, 0, "Type: Meta", 10,140,150,20, 0, 0, 0, 0, 0, "");
767                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
768
769         }
770         else if(last_seq->type==SEQ_SCENE) {
771
772                 uiDefBut(block, LABEL, 0, "Type: Scene", 10,140,150,20, 0, 0, 0, 0, 0, "");
773                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
774                 uiDefButS(block, TOG|BIT|7, SEQ_BUT_RELOAD, "Reverse Frames", 10,90,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Reverse frame order");
775         }
776         else if(last_seq->type==SEQ_MOVIE) {
777
778                 if(last_seq->mul==0.0) last_seq->mul= 1.0;
779
780                 uiDefBut(block, LABEL, 0, "Type: Movie", 10,140,150,20, 0, 0, 0, 0, 0, "");
781                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
782
783                 uiDefButBitS(block, TOG, SEQ_MAKE_PREMUL, SEQ_BUT_RELOAD, "Make Premul Alpha ", 10,90,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Converts RGB values to become premultiplied with Alpha");
784                 uiDefButBitS(block, TOG, SEQ_FILTERY, SEQ_BUT_RELOAD, "FilterY ",       10,70,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "For video movies to remove fields");
785                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Mul:",                   10,50,150,19, &last_seq->mul, 0.001, 5.0, 100, 0, "Multiply colors");
786                 
787                 uiDefButS(block, TOG|BIT|7, SEQ_BUT_RELOAD, "Reverse Frames", 10,30,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Reverse frame order");
788                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Strobe:",                        10,10,150,19, &last_seq->strobe, 1.0, 30.0, 100, 0, "Only display every nth frame");
789
790         }
791         else if(last_seq->type==SEQ_SOUND) {
792
793                 uiDefBut(block, LABEL, 0, "Type: Audio", 10,140,150,20, 0, 0, 0, 0, 0, "");
794                 uiDefBut(block, TEX, 0, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
795
796                 uiDefButBitS(block, TOG, SEQ_MUTE, B_NOP, "Mute", 10,90,120,19, &last_seq->flag, 0.0, 21.0, 100, 0, "");
797                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Gain (dB):", 10,70,150,19, &last_seq->level, -96.0, 6.0, 100, 0, "");
798                 uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Pan:",   10,50,150,19, &last_seq->pan, -1.0, 1.0, 100, 0, "");
799         }
800         else if(last_seq->type>=SEQ_EFFECT) {
801                 uiDefBut(block, LABEL, 0, "Type: Effect", 10,140,150,20, 0, 0, 0, 0, 0, "");
802                 uiDefBut(block, TEX, B_NOP, "Name: ", 10,120,150,19, last_seq->name+2, 0.0, 21.0, 100, 0, "");
803
804                 if(last_seq->type==SEQ_WIPE){
805                         WipeVars *wipe = (WipeVars *)last_seq->effectdata;
806                         char formatstring[256];
807                         strncpy(formatstring, "Transition Type %t|Single Wipe%x0|Double Wipe %x1|Iris Wipe %x4|Clock Wipe %x5", 255);
808                         uiDefButS(block, MENU,SEQ_BUT_EFFECT, formatstring,     10,90,220,22, &wipe->wipetype, 0, 0, 0, 0, "What type of wipe should be performed");
809                         uiDefButF(block, NUM,SEQ_BUT_EFFECT,"Blur:",    10,65,220,22, &wipe->edgeWidth,0.0,1.0, 1, 2, "The percent width of the blur edge");
810                         switch(wipe->wipetype){ /*Skip Types that do not require angle*/
811                                 case DO_IRIS_WIPE:
812                                 case DO_CLOCK_WIPE:
813                                 break;
814                                 
815                                 default:
816                                         uiDefButF(block, NUM,SEQ_BUT_EFFECT,"Angle:",   10,40,220,22, &wipe->angle,-90.0,90.0, 1, 2, "The Angle of the Edge");
817                         }
818                         uiDefButS(block, TOG,SEQ_BUT_EFFECT,"Wipe In",  10,15,220,22, &wipe->forward,0,0, 0, 0, "Controls Primary Direction of Wipe");                          
819                 }
820                 else if(last_seq->type==SEQ_GLOW){
821                         GlowVars *glow = (GlowVars *)last_seq->effectdata;
822
823                         uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Threshold:",     10,90,150,19, &glow->fMini, 0.0, 1.0, 0, 0, "Trigger Intensity");
824                         uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Clamp:",         10,70,150,19, &glow->fClamp, 0.0, 1.0, 0, 0, "Brightness limit of intensity");
825                         uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Boost factor:",  10,50,150,19, &glow->fBoost, 0.0, 10.0, 0, 0, "Brightness multiplier");
826                         uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Blur distance:",         10,30,150,19, &glow->dDist, 0.5, 20.0, 0, 0, "Radius of glow effect");
827                         uiDefButI(block, NUM, B_NOP, "Quality:", 10,10,150,19, &glow->dQuality, 1.0, 5.0, 0, 0, "Accuracy of the blur effect");
828                         uiDefButI(block, TOG, B_NOP, "Only boost", 10,-10,150,19, &glow->bNoComp, 0.0, 0.0, 0, 0, "Show the glow buffer only");
829                 }
830
831         }
832
833
834 }
835
836 static void seq_blockhandlers(ScrArea *sa)
837 {
838         SpaceSeq *sseq= sa->spacedata.first;
839         short a;
840
841         /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */
842         uiFreeBlocksWin(&sa->uiblocks, sa->win);
843
844         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
845                 switch(sseq->blockhandler[a]) {
846
847                 case SEQ_HANDLER_PROPERTIES:
848                         seq_panel_properties(sseq->blockhandler[a+1]);
849                         break;
850
851                 }
852                 /* clear action value for event */
853                 sseq->blockhandler[a+1]= 0;
854         }
855         uiDrawBlocksPanels(sa, 0);
856
857 }
858
859 void drawseqspace(ScrArea *sa, void *spacedata)
860 {
861         SpaceSeq *sseq;
862         Editing *ed;
863         Sequence *seq;
864         float col[3];
865         int ofsx, ofsy;
866
867         ed= G.scene->ed;
868
869         sseq= curarea->spacedata.first;
870         if(sseq->mainb==1) {
871                 draw_image_seq(curarea);
872                 return;
873         }
874
875         bwin_clear_viewmat(sa->win);    /* clear buttons view */
876         glLoadIdentity();
877
878         BIF_GetThemeColor3fv(TH_BACK, col);
879         if(ed && ed->metastack.first) glClearColor(col[0], col[1], col[2]-0.1, 0.0);
880         else glClearColor(col[0], col[1], col[2], 0.0);
881
882         glClear(GL_COLOR_BUFFER_BIT);
883
884         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
885
886         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
887                 if(G.v2d->scroll) {
888                         ofsx= curarea->winrct.xmin;     /* because of mywin */
889                         ofsy= curarea->winrct.ymin;
890                         glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
891                         glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
892                 }
893         }
894
895
896         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
897
898         BIF_ThemeColorShade(TH_BACK, -20);
899         glRectf(G.v2d->cur.xmin,  0.0,  G.v2d->cur.xmax,  1.0);
900
901         boundbox_seq();
902         calc_ipogrid();
903         draw_ipogrid();
904         draw_cfra_seq();
905
906         /* sequences: first deselect */
907
908         if(ed) {
909                 seq= ed->seqbasep->first;
910                 while(seq) { /* bound box test, dont draw outside the view */
911                         if (seq->flag & SELECT ||
912                                         seq->start > G.v2d->cur.xmax ||
913                                         seq->start+seq->len < G.v2d->cur.xmin ||
914                                         seq->machine+1.0 < G.v2d->cur.ymin ||
915                                         seq->machine > G.v2d->cur.ymax)
916                         {
917                                 /* dont draw */
918                         } else {
919                                 drawseq(seq, sa);
920                         }
921                         seq= seq->next;
922                 }
923         }
924         ed= G.scene->ed;
925         if(ed) {
926                 seq= ed->seqbasep->first;
927                 while(seq) { /* bound box test, dont draw outside the view */
928                         if (!(seq->flag & SELECT) ||
929                                         seq->start > G.v2d->cur.xmax ||
930                                         seq->start+seq->len < G.v2d->cur.xmin ||
931                                         seq->machine+1.0 < G.v2d->cur.ymin ||
932                                         seq->machine > G.v2d->cur.ymax)
933                         {
934                                 /* dont draw */
935                         } else {
936                                 drawseq(seq, sa);
937                         }
938                         seq= seq->next;
939                 }
940         }
941
942         draw_extra_seqinfo();
943
944         /* restore viewport */
945         mywinset(curarea->win);
946
947         /* ortho at pixel level curarea */
948         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
949
950         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
951                 if(G.v2d->scroll) {
952                         drawscroll(0);
953                 }
954         }
955
956         draw_area_emboss(sa);
957
958         if(sseq->mainb==0) {
959                 /* it is important to end a view in a transform compatible with buttons */
960                 bwin_scalematrix(sa->win, sseq->blockscale, sseq->blockscale, sseq->blockscale);
961                 seq_blockhandlers(sa);
962         }
963
964         curarea->win_swap= WIN_BACK_OK;
965 }
966
967