More Orange NLA/Action fixes;
[blender.git] / source / blender / src / drawaction.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  * Drawing routines for the Action window type
32  */
33
34 /* System includes ----------------------------------------------------- */
35
36 #include <math.h>
37 #include <stdlib.h>
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include "MEM_guardedalloc.h"
44
45 #include "BMF_Api.h"
46
47 #include "BLI_blenlib.h"
48 #include "BLI_arithb.h"
49
50 /* Types --------------------------------------------------------------- */
51 #include "DNA_action_types.h"
52 #include "DNA_curve_types.h"
53 #include "DNA_ipo_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_screen_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_space_types.h"
58 #include "DNA_constraint_types.h"
59 #include "DNA_key_types.h"
60
61 #include "BKE_action.h"
62 #include "BKE_ipo.h"
63 #include "BKE_global.h"
64
65 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
66
67 #include "BIF_editaction.h"
68 #include "BIF_editkey.h"
69 #include "BIF_interface.h"
70 #include "BIF_gl.h"
71 #include "BIF_glutil.h"
72 #include "BIF_resources.h"
73 #include "BIF_screen.h"
74 #include "BIF_mywindow.h"
75 #include "BIF_space.h"
76
77 #include "BDR_drawaction.h"
78 #include "BDR_editcurve.h"
79
80 #include "BSE_view.h"
81 #include "BSE_drawnla.h"
82 #include "BSE_drawipo.h"
83
84 /* 'old' stuff": defines and types, and own include -------------------- */
85
86 #include "blendef.h"
87 #include "mydevice.h"
88
89
90 /* local functions ----------------------------------------------------- */
91 void drawactionspace(ScrArea *sa, void *spacedata);
92 static void draw_channel_names(void);
93 static void draw_channel_strips(SpaceAction *saction);
94 int count_action_levels(bAction *act);
95 static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert);
96 static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert);
97 static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert);
98 static BezTriple **icu_to_keylist(IpoCurve *icu, int flags, int *totvert);
99 static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos);
100 void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, int flags, float ypos);
101 static void draw_action_mesh_names(Key *key);
102
103 /* missing local prototypes -------------------------------------------- */
104 void meshactionbuts(SpaceAction *saction, Key *key);
105 void do_actionbuts(unsigned short event);
106
107 /* implementation ------------------------------------------------------ */
108
109 extern short showsliders; /* editaction .c */
110 extern short ACTWIDTH;
111
112 void meshactionbuts(SpaceAction *saction, Key *key)
113 {
114         int           i;
115         char          str[64];
116         float           x, y;
117         uiBlock       *block;
118         uiBut             *but;
119
120 #define XIC 20
121 #define YIC 20
122
123         /* lets make the rvk sliders */
124
125         /* reset the damn myortho2 or the sliders won't draw/redraw
126          * correctly *grumble*
127          */
128         mywinset(curarea->win);
129         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
130
131     sprintf(str, "actionbuttonswin %d", curarea->win);
132     block= uiNewBlock (&curarea->uiblocks, str, 
133                        UI_EMBOSS, UI_HELV, curarea->win);
134
135         x = NAMEWIDTH + 1;
136     y = key->totkey*(CHANNELHEIGHT+CHANNELSKIP) 
137           + CHANNELHEIGHT/2  - G.v2d->cur.ymin;
138
139         /* make the little 'open the sliders' widget */
140     BIF_ThemeColor(TH_FACE); // this slot was open...
141         glRects(2,            y + 2*CHANNELHEIGHT - 2,  
142                         ACTWIDTH - 2, y + CHANNELHEIGHT + 2);
143         glColor3ub(0, 0, 0);
144         glRasterPos2f(4, y + CHANNELHEIGHT + 6);
145         BMF_DrawString(G.font, "Sliders");
146
147         uiBlockSetEmboss(block, UI_EMBOSSN);
148
149         if (!showsliders) {
150                 ACTWIDTH = NAMEWIDTH;
151                 but=uiDefIconButS(block, TOG, B_REDR, 
152                                           ICON_DISCLOSURE_TRI_RIGHT,
153                                           NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
154                                           XIC,YIC-2,
155                                           &(showsliders), 0, 0, 0, 0, 
156                                           "Show action window sliders");
157                 // no hilite, the winmatrix is not correct later on...
158                 uiButSetFlag(but, UI_NO_HILITE);
159
160         }
161         else {
162                 but= uiDefIconButS(block, TOG, B_REDR, 
163                                           ICON_DISCLOSURE_TRI_DOWN,
164                                           NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
165                                           XIC,YIC-2,
166                                           &(showsliders), 0, 0, 0, 0, 
167                                           "Hide action window sliders");
168                 // no hilite, the winmatrix is not correct later on...
169                 uiButSetFlag(but, UI_NO_HILITE);
170                                           
171                 ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
172
173                 /* sliders are open so draw them */
174                 BIF_ThemeColor(TH_FACE); 
175
176                 glRects(NAMEWIDTH,  0,  NAMEWIDTH+SLIDERWIDTH,  curarea->winy);
177                 uiBlockSetEmboss(block, UI_EMBOSS);
178                 for (i=1 ; i < key->totkey ; ++ i) {
179                         make_rvk_slider(block, key, i, 
180                                                         x, y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
181
182                         y-=CHANNELHEIGHT+CHANNELSKIP;
183                         
184                 }
185         }
186         uiDrawBlock(block);
187
188 }
189
190 void draw_cfra_action(void)
191 {
192         Object *ob;
193         float vec[2];
194         
195         vec[0]= (G.scene->r.cfra);
196         vec[0]*= G.scene->r.framelen;
197         
198         vec[1]= G.v2d->cur.ymin;
199         glColor3ub(0x60, 0xc0, 0x40);
200         glLineWidth(2.0);
201         
202         glBegin(GL_LINE_STRIP);
203         glVertex2fv(vec);
204         vec[1]= G.v2d->cur.ymax;
205         glVertex2fv(vec);
206         glEnd();
207         
208         ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
209         if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
210                 vec[0]-= ob->sf;
211                 
212                 glColor3ub(0x10, 0x60, 0);
213                 
214                 glBegin(GL_LINE_STRIP);
215                 glVertex2fv(vec);
216                 vec[1]= G.v2d->cur.ymin;
217                 glVertex2fv(vec);
218                 glEnd();
219         }
220         
221         glLineWidth(1.0);
222 }
223
224
225 static void draw_action_channel_names(bAction   *act) 
226 {
227     bActionChannel *chan;
228     bConstraintChannel *conchan;
229     float       x, y;
230
231     x = 0.0;
232         y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
233
234         for (chan=act->chanbase.first; chan; chan=chan->next){
235                 BIF_ThemeColorShade(TH_HEADER, 20);
236                 glRectf(x,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
237         
238                 if (chan->flag & ACHAN_SELECTED)
239                         BIF_ThemeColor(TH_TEXT_HI);
240                 else
241                         BIF_ThemeColor(TH_TEXT);
242                 glRasterPos2f(x+8,  y-4);
243                 BMF_DrawString(G.font, chan->name);
244                 y-=CHANNELHEIGHT+CHANNELSKIP;
245         
246                 /* Draw constraint channels */
247                 for (conchan=chan->constraintChannels.first; 
248                                 conchan; conchan=conchan->next){
249                         if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
250                                 BIF_ThemeColor(TH_TEXT_HI);
251                         else
252                                 BIF_ThemeColor(TH_TEXT);
253                                 
254                         glRasterPos2f(x+32,  y-4);
255                         BMF_DrawString(G.font, conchan->name);
256                         y-=CHANNELHEIGHT+CHANNELSKIP;
257                 }
258         }
259 }
260
261
262 static void draw_action_mesh_names(Key *key) 
263 {
264         /* draws the names of the rvk keys in the
265          * left side of the action window
266          */
267         int          i;
268         char     keyname[32];
269         float    x, y;
270         KeyBlock *kb;
271
272         x = 0.0;
273         y= key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
274
275         kb= key->block.first;
276
277         for (i=1 ; i < key->totkey ; ++ i) {
278                 glColor3ub(0xAA, 0xAA, 0xAA);
279                 glRectf(x,      y-CHANNELHEIGHT/2,      (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
280
281                 glColor3ub(0, 0, 0);
282
283                 glRasterPos2f(x+8,      y-4);
284                 kb = kb->next;
285                 /* Blender now has support for named
286                  * key blocks. If a name hasn't
287                  * been set for an key block then
288                  * just display the key number -- 
289                  * otherwise display the name stored
290                  * in the keyblock.
291                  */
292                 if (kb->name[0] == '\0') {
293                   sprintf(keyname, "Key %d", i);
294                   BMF_DrawString(G.font, keyname);
295                 }
296                 else {
297                   BMF_DrawString(G.font, kb->name);
298                 }
299
300                 y-=CHANNELHEIGHT+CHANNELSKIP;
301
302         }
303 }
304
305 static void draw_channel_names(void) 
306 {
307         short ofsx, ofsy = 0; 
308         bAction *act;
309         Key *key;
310
311         /* Clip to the scrollable area */
312         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
313                 if(G.v2d->scroll) {     
314                         ofsx= curarea->winrct.xmin;     
315                         ofsy= curarea->winrct.ymin;
316                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
317                                            (ofsy+G.v2d->mask.ymax) -
318                                            (ofsy+G.v2d->mask.ymin)); 
319                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
320                                           (ofsy+G.v2d->mask.ymax) -
321                                           (ofsy+G.v2d->mask.ymin));
322                 }
323         }
324         
325         myortho2(0,     NAMEWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);   //      Scaling
326         
327         glColor3ub(0x00, 0x00, 0x00);
328
329         act=G.saction->action;
330
331         if (act) {
332                 /* if there is a selected action then
333                  * draw the channel names
334                  */
335                 draw_action_channel_names(act);
336         }
337         if ( (key = get_action_mesh_key()) ) {
338                 /* if there is a mesh selected with rvk's,
339                         * then draw the RVK names
340                         */
341                 draw_action_mesh_names(key);
342     }
343
344     myortho2(0, NAMEWIDTH, 0, (ofsy+G.v2d->mask.ymax) -
345               (ofsy+G.v2d->mask.ymin)); //      Scaling
346
347 }
348
349 int count_action_levels(bAction *act)
350 {
351         int y=0;
352         bActionChannel *achan;
353
354         if (!act)
355                 return 0;
356
357         for (achan=act->chanbase.first; achan; achan=achan->next){
358                 y+=1;
359                 y+=BLI_countlist(&achan->constraintChannels);
360         }
361
362         return y;
363 }
364
365 static void draw_channel_strips(SpaceAction *saction)
366 {
367         rcti scr_rct;
368         gla2DDrawInfo *di;
369         bAction *act;
370         bActionChannel *chan;
371         bConstraintChannel *conchan;
372         float   y;
373         int act_start, act_end, dummy;
374         char col1[3], col2[3];
375         
376         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
377         BIF_GetThemeColor3ubv(TH_HILITE, col1);
378
379         act= saction->action;
380         if (!act)
381                 return;
382
383         scr_rct.xmin= saction->area->winrct.xmin + saction->v2d.mask.xmin;
384         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
385         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
386         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
387         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
388
389         /* if in NLA there's a strip active, map the view */
390         if (G.saction->pin==0 && OBACT)
391                 map_active_strip(di, OBACT, 0);
392         
393         /* start and end of action itself */
394         gla2DDrawTranslatePt(di, calc_action_start(act), 0, &act_start, &dummy);
395         gla2DDrawTranslatePt(di, calc_action_end(act), 0, &act_end, &dummy);
396         
397         if (G.saction->pin==0 && OBACT)
398                 map_active_strip(di, OBACT, 1);
399         
400         /* first backdrop strips */
401         y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
402         glEnable(GL_BLEND);
403         for (chan=act->chanbase.first; chan; chan=chan->next){
404                 int frame1_x, channel_y;
405                 
406                 gla2DDrawTranslatePt(di, G.v2d->cur.xmin, y, &frame1_x, &channel_y);
407                 
408                 if (chan->flag & ACHAN_SELECTED) glColor4ub(col1[0], col1[1], col1[2], 0x22);
409                 else glColor4ub(col2[0], col2[1], col2[2], 0x22);
410                 glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
411                 
412                 if (chan->flag & ACHAN_SELECTED) glColor4ub(col1[0], col1[1], col1[2], 0x22);
413                 else glColor4ub(col2[0], col2[1], col2[2], 0x22);
414                 glRectf(act_start,  channel_y-CHANNELHEIGHT/2,  act_end,  channel_y+CHANNELHEIGHT/2);
415                 
416                 /*      Increment the step */
417                 y-=CHANNELHEIGHT+CHANNELSKIP;
418                 
419                 /* Draw constraint channels */
420                 for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
421                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
422                         
423                         if (conchan->flag & ACHAN_SELECTED) glColor4ub(col1[0], col1[1], col1[2], 0x22);
424                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
425                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
426                         
427                         if (conchan->flag & ACHAN_SELECTED) glColor4ub(col1[0], col1[1], col1[2], 0x22);
428                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
429                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2+4,  act_end,  channel_y+CHANNELHEIGHT/2-4);
430                         
431                         y-=CHANNELHEIGHT+CHANNELSKIP;
432                 }
433         }               
434         glDisable(GL_BLEND);
435         
436         if (G.saction->pin==0 && OBACT)
437                 map_active_strip(di, OBACT, 0);
438         
439         /* dot thingies */
440         y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
441         for (chan=act->chanbase.first; chan; chan=chan->next){
442                 draw_ipo_channel(di, chan->ipo, 0, y);
443                 y-=CHANNELHEIGHT+CHANNELSKIP;
444
445                 /* Draw constraint channels */
446                 for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
447                         draw_ipo_channel(di, conchan->ipo, 0, y);
448                         y-=CHANNELHEIGHT+CHANNELSKIP;
449                 }
450         }
451
452         glaEnd2DDraw(di);
453 }
454
455 static void draw_mesh_strips(SpaceAction *saction, Key *key)
456 {
457         /* draw the RVK keyframes as those little square button things
458          */
459         rcti scr_rct;
460         gla2DDrawInfo *di;
461         float   y, ybase;
462         IpoCurve *icu;
463         char col1[3], col2[3];
464         
465         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
466         BIF_GetThemeColor3ubv(TH_HILITE, col1);
467
468         if (!key->ipo) return;
469
470         scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
471         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
472         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
473         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
474         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
475
476         ybase = key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
477
478         for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
479
480                 int frame1_x, channel_y;
481
482                 /* lets not deal with the "speed" Ipo
483                  */
484                 if (icu->adrcode==0) continue;
485
486                 y = ybase       - (CHANNELHEIGHT+CHANNELSKIP)*(icu->adrcode-1);
487                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
488
489                 /* all frames that have a frame number less than one
490                  * get a desaturated orange background
491                  */
492                 glEnable(GL_BLEND);
493                 glColor4ub(col2[0], col2[1], col2[2], 0x22);
494                 glRectf(0,        channel_y-CHANNELHEIGHT/2,  
495                                 frame1_x, channel_y+CHANNELHEIGHT/2);
496
497                 /* frames one and higher get a saturated orange background
498                  */
499                 glColor4ub(col2[0], col2[1], col2[2], 0x44);
500                 glRectf(frame1_x,         channel_y-CHANNELHEIGHT/2,  
501                                 G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
502                 glDisable(GL_BLEND);
503
504                 /* draw the little squares
505                  */
506                 draw_icu_channel(di, icu, 0, y); 
507         }
508
509         glaEnd2DDraw(di);
510 }
511
512 /* ********* action panel *********** */
513
514
515 void do_actionbuts(unsigned short event)
516 {
517         switch(event) {
518         case REDRAWVIEW3D:
519                 allqueue(REDRAWVIEW3D, 0);
520                 break;
521         case B_REDR:
522                 allqueue(REDRAWACTION, 0);
523                 break;
524         }
525 }
526
527
528 static void action_panel_properties(short cntrl)        // ACTION_HANDLER_PROPERTIES
529 {
530         uiBlock *block;
531
532         block= uiNewBlock(&curarea->uiblocks, "action_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
533         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
534         uiSetPanelHandler(ACTION_HANDLER_PROPERTIES);  // for close and esc
535         if(uiNewPanel(curarea, block, "Transform Properties", "Action", 10, 230, 318, 204)==0) return;
536
537         uiDefBut(block, LABEL, 0, "test text",          10,180,300,19, 0, 0, 0, 0, 0, "");
538
539 }
540
541 static void action_blockhandlers(ScrArea *sa)
542 {
543         SpaceAction *sact= sa->spacedata.first;
544         short a;
545         
546         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
547                 switch(sact->blockhandler[a]) {
548
549                 case ACTION_HANDLER_PROPERTIES:
550                         action_panel_properties(sact->blockhandler[a+1]);
551                         break;
552                 
553                 }
554                 /* clear action value for event */
555                 sact->blockhandler[a+1]= 0;
556         }
557         uiDrawBlocksPanels(sa, 0);
558 }
559
560 void drawactionspace(ScrArea *sa, void *spacedata)
561 {
562         short ofsx = 0, ofsy = 0;
563         Key *key;
564         float col[3];
565         short maxymin;
566
567         if (!G.saction)
568                 return;
569
570         /* warning; blocks need to be freed each time, handlers dont remove  */
571         uiFreeBlocksWin(&sa->uiblocks, sa->win);
572
573         if (!G.saction->pin) {
574                 if (OBACT)
575                         G.saction->action = OBACT->action;
576                 else
577                         G.saction->action=NULL;
578         }
579         key = get_action_mesh_key();
580
581         /* Damn I hate hunting to find my rvk's because
582          * they have scrolled off of the screen ... this
583          * oughta fix it
584          */
585                    
586         if (key) {
587                 if (G.v2d->cur.ymin < -CHANNELHEIGHT) 
588                         G.v2d->cur.ymin = -CHANNELHEIGHT;
589                 
590                 maxymin = key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
591                 if (G.v2d->cur.ymin > maxymin) G.v2d->cur.ymin = maxymin;
592         }
593
594         /* Lets make sure the width of the left hand of the screen
595          * is set to an appropriate value based on whether sliders
596          * are showing of not
597          */
598         if (key && showsliders) ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
599         else ACTWIDTH = NAMEWIDTH;
600
601         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
602
603         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
604
605         /* background color for entire window (used in lefthand part tho) */
606         BIF_GetThemeColor3fv(TH_HEADER, col);
607         glClearColor(col[0], col[1], col[2], 0.0); 
608         glClear(GL_COLOR_BUFFER_BIT);
609         
610         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
611                 if(G.v2d->scroll) {     
612                         ofsx= curarea->winrct.xmin;     
613                         ofsy= curarea->winrct.ymin;
614                         glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
615                                            ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
616                                            ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
617                         glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
618                                           ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
619                                           ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
620                 }
621         }
622
623         BIF_GetThemeColor3fv(TH_BACK, col);
624         glClearColor(col[0], col[1], col[2], 0.0);
625         glClear(GL_COLOR_BUFFER_BIT);
626
627         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
628         bwin_clear_viewmat(sa->win);    /* clear buttons view */
629         glLoadIdentity();
630
631         /*      Draw backdrop */
632         calc_ipogrid(); 
633         draw_ipogrid();
634
635         /* Draw channel strips */
636         draw_channel_strips(G.saction);
637
638         if (key) {
639                 /* if there is a mesh with rvk's selected,
640                  * then draw the key frames in the action window
641                  */
642                 draw_mesh_strips(G.saction, key);
643         }
644
645         /* Draw current frame */
646         glViewport(ofsx+G.v2d->mask.xmin,  
647              ofsy+G.v2d->mask.ymin, 
648              ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
649              ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
650         glScissor(ofsx+G.v2d->mask.xmin,  
651             ofsy+G.v2d->mask.ymin, 
652             ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
653             ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
654         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax,  G.v2d->cur.ymin, G.v2d->cur.ymax);
655         draw_cfra_action();
656
657         /* Draw scroll */
658         mywinset(curarea->win); // reset scissor too
659         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
660       myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
661       if(G.v2d->scroll) drawscroll(0);
662         }
663
664         if(G.v2d->mask.xmin!=0) {
665                 /* Draw channel names */
666                 draw_channel_names();
667
668                 if(sa->winx > 50 + NAMEWIDTH + SLIDERWIDTH) {
669                         if ( key ) {
670                                 /* if there is a mesh with rvk's selected,
671                                  * then draw the key frames in the action window
672                                  */
673                                 meshactionbuts(G.saction, key);
674                         }
675                 }
676         }
677         
678         mywinset(curarea->win); // reset scissor too
679         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
680         draw_area_emboss(sa);
681
682         /* it is important to end a view in a transform compatible with buttons */
683         bwin_scalematrix(sa->win, G.saction->blockscale, G.saction->blockscale, G.saction->blockscale);
684         action_blockhandlers(sa);
685
686         curarea->win_swap= WIN_BACK_OK;
687 }
688
689
690 /** Draw a nicely beveled button (in screen space) */
691 static void draw_bevel_but(int x, int y, int w, int h, int sel)
692 {
693         int xmin= x, ymin= y;
694         int xmax= x+w-1, ymax= y+h-1;
695         
696         /* outline */
697         glColor3ub(0,0,0);
698         glBegin(GL_LINE_LOOP);
699         glVertex2i(xmin, ymin);
700         glVertex2i(xmax, ymin);
701         glVertex2i(xmax, ymax);
702         glVertex2i(xmin, ymax);
703         glEnd();
704         
705         /* interior */
706         if (sel) glColor3ub(0xF1, 0xCA, 0x13);
707         else glColor3ub(0xAC, 0xAC, 0xAC);
708         glRectf(xmin+1, ymin+1, xmax-1, ymax-1);
709         
710         /* bevel */
711         glBegin(GL_LINE_LOOP);
712         
713         if (sel) glColor3ub(0xD0, 0x7E, 0x06);
714         else glColor3ub(0x8C, 0x8C, 0x8C);
715         glVertex2i(xmax-1, ymin+1);
716         glVertex2i(xmax-1, ymax-1);
717         
718         if (sel) glColor3ub(0xF4, 0xEE, 0x8E);
719         else glColor3ub(0xDF, 0xDF, 0xDF);
720         glVertex2i(xmin+1, ymax-1);
721         glVertex2i(xmin+1, ymin+1);
722         glEnd();
723 }
724
725 static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos)
726 {
727         int v;
728
729         if (!blist)
730                 return;
731
732         for (v = 0; v<totvert; v++){
733                 if (v==0 || (blist[v]->vec[1][0] != blist[v-1]->vec[1][0])){
734                         int sc_x, sc_y;
735                         gla2DDrawTranslatePt(di, blist[v]->vec[1][0], ypos, &sc_x, &sc_y);
736                         draw_bevel_but(sc_x-2, sc_y-7, 7, 13, (blist[v]->f2 & 1));
737                 }
738         }                       
739 }
740
741 void draw_object_channel(gla2DDrawInfo *di, Object *ob, int flags, float ypos)
742 {
743         BezTriple **blist;
744         int totvert;
745
746         blist = ob_to_keylist(ob, flags, &totvert);
747         if (blist){
748                 draw_keylist(di,totvert, blist, ypos);
749                 MEM_freeN(blist);
750         }
751 }
752
753 void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, int flags, float ypos)
754 {
755         BezTriple **blist;
756         int totvert;
757
758         blist = ipo_to_keylist(ipo, flags, &totvert);
759         if (blist){
760                 draw_keylist(di,totvert, blist, ypos);
761                 MEM_freeN(blist);
762         }
763 }
764
765 void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, int flags, float ypos)
766 {
767         /* draw the keys for an IpoCurve
768          */
769         BezTriple **blist;
770         int totvert;
771
772         blist = icu_to_keylist(icu, flags, &totvert);
773         if (blist){
774                 draw_keylist(di,totvert, blist, ypos);
775                 MEM_freeN(blist);
776         }
777 }
778
779 void draw_action_channel(gla2DDrawInfo *di, bAction *act, int flags, float ypos)
780 {
781         BezTriple **blist;
782         int totvert;
783
784         blist = action_to_keylist(act, flags, &totvert);
785         if (blist){
786                 draw_keylist(di,totvert, blist, ypos);
787                 MEM_freeN(blist);
788         }
789 }
790
791 static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert)
792 {
793         IpoCurve *icu;
794         bConstraintChannel *conchan;
795         int v, count=0;
796
797         BezTriple **list = NULL;
798
799         if (ob){
800
801                 /* Count Object Keys */
802                 if (ob->ipo){
803                         for (icu=ob->ipo->curve.first; icu; icu=icu->next){
804                                 count+=icu->totvert;
805                         }
806                 }
807                 
808                 /* Count Constraint Keys */
809                 for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
810                         if(conchan->ipo)
811                                 for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
812                                         count+=icu->totvert;
813                 }
814                 
815                 /* Count object data keys */
816
817                 /* Build the list */
818                 if (count){
819                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
820                         count=0;
821                         
822                         /* Add object keyframes */
823                         if(ob->ipo) {
824                                 for (icu=ob->ipo->curve.first; icu; icu=icu->next){
825                                         for (v=0; v<icu->totvert; v++){
826                                                 list[count++]=&icu->bezt[v];
827                                         }
828                                 }
829                         }                       
830                         /* Add constraint keyframes */
831                         for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
832                                 if(conchan->ipo)
833                                         for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
834                                                 for (v=0; v<icu->totvert; v++)
835                                                         list[count++]=&icu->bezt[v];
836                         }
837                         
838                         /* Add object data keyframes */
839
840                         /* Sort */
841                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
842                 }
843         }
844         (*totvert)=count;
845         return list;
846 }
847
848 static BezTriple **icu_to_keylist(IpoCurve *icu, int flags, int *totvert)
849 {
850         /* compile a list of all bezier triples in an
851          * IpoCurve.
852          */
853         int v, count = 0;
854
855         BezTriple **list = NULL;
856
857         count=icu->totvert;
858
859         if (count){
860                 list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
861                 count=0;
862                         
863                 for (v=0; v<icu->totvert; v++){
864                         list[count++]=&icu->bezt[v];
865                 }
866                 qsort(list, count, sizeof(BezTriple*), bezt_compare);
867         }
868         (*totvert)=count;
869         return list;
870
871 }
872
873 static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert)
874 {
875         IpoCurve *icu;
876         int v, count=0;
877
878         BezTriple **list = NULL;
879
880         if (ipo){
881                 /* Count required keys */
882                 for (icu=ipo->curve.first; icu; icu=icu->next){
883                         count+=icu->totvert;
884                 }
885                 
886                 /* Build the list */
887                 if (count){
888                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
889                         count=0;
890                         
891                         for (icu=ipo->curve.first; icu; icu=icu->next){
892                                 for (v=0; v<icu->totvert; v++){
893                                         list[count++]=&icu->bezt[v];
894                                 }
895                         }                       
896                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
897                 }
898         }
899         (*totvert)=count;
900         return list;
901 }
902
903 static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert)
904 {
905         IpoCurve *icu;
906         bActionChannel *achan;
907         bConstraintChannel *conchan;
908         int v, count=0;
909
910         BezTriple **list = NULL;
911
912         if (act){
913                 /* Count required keys */
914                 for (achan=act->chanbase.first; achan; achan=achan->next){
915                         /* Count transformation keys */
916                         if(achan->ipo) {
917                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next)
918                                         count+=icu->totvert;
919                         }
920                         /* Count constraint keys */
921                         for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
922                                 if(conchan->ipo) 
923                                         for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
924                                                 count+=icu->totvert;
925                                 
926                 }
927                 
928                 /* Build the list */
929                 if (count){
930                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
931                         count=0;
932                         
933                         for (achan=act->chanbase.first; achan; achan=achan->next){
934                                 if(achan->ipo) {
935                                         /* Add transformation keys */
936                                         for (icu=achan->ipo->curve.first; icu; icu=icu->next){
937                                                 for (v=0; v<icu->totvert; v++)
938                                                         list[count++]=&icu->bezt[v];
939                                         }
940                                 }                                       
941                                         /* Add constraint keys */
942                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){
943                                         if(conchan->ipo)
944                                                 for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
945                                                         for (v=0; v<icu->totvert; v++)
946                                                                 list[count++]=&icu->bezt[v];
947                                 }
948                                                         
949                         }               
950                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
951                         
952                 }
953         }
954         (*totvert)=count;
955         return list;
956 }
957