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