Support for using the action window as a tool for modifying
[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 #ifdef WIN32
44 #include "BLI_winstuff.h"
45 #endif
46
47 #include "MEM_guardedalloc.h"
48
49 #include "BMF_Api.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_arithb.h"
53
54 /* Types --------------------------------------------------------------- */
55 #include "DNA_action_types.h"
56 #include "DNA_curve_types.h"
57 #include "DNA_ipo_types.h"
58 #include "DNA_object_types.h"
59 #include "DNA_screen_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_constraint_types.h"
63 #include "DNA_mesh_types.h"
64 #include "DNA_key_types.h"
65
66 #include "BKE_action.h"
67 #include "BKE_global.h"
68
69 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
70
71 #include "BIF_gl.h"
72 #include "BIF_glutil.h"
73 #include "BIF_resources.h"
74 #include "BIF_screen.h"
75 #include "BIF_interface.h"
76 #include "BIF_mywindow.h"
77
78 #include "BDR_editcurve.h"
79 #include "BSE_view.h"
80 #include "BSE_drawipo.h"
81 #include "BSE_editaction.h"
82 #include "BSE_editaction_types.h"
83 #include "BDR_drawaction.h"
84
85 /* 'old' stuff": defines and types, and own include -------------------- */
86
87 #include "blendef.h"
88 #include "interface.h"
89 #include "mydevice.h"
90
91 #include "BKE_ipo.h"
92
93 /* local functions ----------------------------------------------------- */
94 void drawactionspace(ScrArea *sa, void *spacedata);
95 static void draw_channel_names(void);
96 static void draw_channel_strips(SpaceAction *saction);
97 int count_action_levels(bAction *act);
98 static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert);
99 static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert);
100 static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert);
101 static BezTriple **icu_to_keylist(IpoCurve *icu, int flags, int *totvert);
102 static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos);
103 void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, int flags, float ypos);
104 static void draw_action_mesh_names(Key *key);
105
106 /* implementation ------------------------------------------------------ */
107
108 extern void make_rvk_slider(uiBlock *block, Key *key, int i,
109                                                         int x, int y, int w, int h); /* editkey.c */
110 extern short showsliders; /* editaction .c */
111 extern short ACTWIDTH;
112
113 void meshactionbuts(SpaceAction *saction, Key *key)
114 {
115         int           i;
116         char          str[64];
117         char          keyname[32];
118         float           x, y, ybase;
119         uiBlock       *block;
120         uiBut         *but;
121     short ofsx, ofsy = 0; 
122 #define RVKBGCOL .6, .6, .8
123 #define XIC 20
124 #define YIC 20
125
126         /* lets make the rvk sliders */
127
128         /* reset the damn myortho2 or the sliders won't draw/redraw
129          * correctly *grumble*
130          */
131         mywinset(curarea->win);
132         myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
133
134     sprintf(str, "actionbuttonswin %d", curarea->win);
135     block= uiNewBlock (&curarea->uiblocks, str, 
136                        UI_EMBOSSX, UI_HELV, curarea->win);
137
138         x = NAMEWIDTH + 1;
139     y = key->totkey*(CHANNELHEIGHT+CHANNELSKIP) 
140           - CHANNELHEIGHT/2  - G.v2d->cur.ymin;
141
142     uiBlockSetCol(block, BUTPURPLE);
143
144         /* make the little 'open the sliders' widget */
145     glColor3f(RVKBGCOL); 
146         glRects(2,            y + 2*CHANNELHEIGHT - 2,  
147                         ACTWIDTH - 2, y + CHANNELHEIGHT + 2);
148         glColor3ub(0, 0, 0);
149         glRasterPos2f(4, y + CHANNELHEIGHT + 6);
150         BMF_DrawString(G.font, "Sliders");
151
152         uiBlockSetEmboss(block, UI_EMBOSSN);
153
154         if (!showsliders) {
155                 ACTWIDTH = NAMEWIDTH;
156                 uiDefIconButS(block, TOG, B_FLIPINFOMENU, 
157                                           ICON_DISCLOSURE_TRI_RIGHT,
158                                           NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
159                                           XIC,YIC-2,
160                                           &(showsliders), 0, 0, 0, 0, 
161                                           "Show action window sliders");
162         }
163         else {
164                 uiDefIconButS(block, TOG, B_FLIPINFOMENU, 
165                                           ICON_DISCLOSURE_TRI_DOWN,
166                                           NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
167                                           XIC,YIC-2,
168                                           &(showsliders), 0, 0, 0, 0, 
169                                           "Hide action window sliders");
170                 ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
171
172                 /* sliders are open so draw them */
173                 glColor3f(RVKBGCOL); 
174                 glRects(NAMEWIDTH,  0,  NAMEWIDTH+SLIDERWIDTH,  curarea->winy);
175                 uiBlockSetEmboss(block, UI_EMBOSSX);
176                 for (i=1 ; i < key->totkey ; ++ i) {
177                         make_rvk_slider(block, key, i, 
178                                                         x, y, SLIDERWIDTH-2, CHANNELHEIGHT-1);
179
180                         y-=CHANNELHEIGHT+CHANNELSKIP;
181                         
182                 }
183         }
184         uiDrawBlock(block);
185
186 }
187
188 void draw_cfra_action(void)
189 {
190         Object *ob;
191         float vec[2];
192         
193         vec[0]= (G.scene->r.cfra);
194         vec[0]*= G.scene->r.framelen;
195         
196         vec[1]= G.v2d->cur.ymin;
197         glColor3ub(0x60, 0xc0, 0x40);
198         glLineWidth(2.0);
199         
200         glBegin(GL_LINE_STRIP);
201         glVertex2fv(vec);
202         vec[1]= G.v2d->cur.ymax;
203         glVertex2fv(vec);
204         glEnd();
205         
206         ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
207         if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
208                 vec[0]-= ob->sf;
209                 
210                 glColor3ub(0x10, 0x60, 0);
211                 
212                 glBegin(GL_LINE_STRIP);
213                 glVertex2fv(vec);
214                 vec[1]= G.v2d->cur.ymin;
215                 glVertex2fv(vec);
216                 glEnd();
217         }
218         
219         glLineWidth(1.0);
220 }
221
222
223 static void draw_action_channel_names(bAction   *act) {
224     bActionChannel *chan;
225     bConstraintChannel *conchan;
226     float       x, y;
227
228     x = 0.0;
229                 y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
230
231                 for (chan=act->chanbase.first; chan; chan=chan->next){
232         glColor3ub(0xAA, 0xAA, 0xAA);
233         glRectf(x,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
234
235         if (chan->flag & ACHAN_SELECTED)
236             glColor3ub(255, 255, 255);
237         else
238             glColor3ub(0, 0, 0);
239         glRasterPos2f(x+8,  y-4);
240         BMF_DrawString(G.font, chan->name);
241         y-=CHANNELHEIGHT+CHANNELSKIP;
242
243         /* Draw constraint channels */
244         for (conchan=chan->constraintChannels.first; 
245              conchan; conchan=conchan->next){
246             if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
247                 glColor3ub(255, 255, 255);
248             else
249                 glColor3ub(0, 0, 0);
250                                 
251             glRasterPos2f(x+32,  y-4);
252             BMF_DrawString(G.font, conchan->name);
253             y-=CHANNELHEIGHT+CHANNELSKIP;
254         }
255                 }
256 }
257
258
259 static void draw_action_mesh_names(Key *key) {
260         /* draws the names of the rvk keys in the
261          * left side of the action window
262          */
263         int          i;
264         char     keyname[32];
265         float    x, y;
266         KeyBlock *kb;
267
268         x = 0.0;
269         y= key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
270
271         kb= key->block.first;
272
273         for (i=1 ; i < key->totkey ; ++ i) {
274                 glColor3ub(0xAA, 0xAA, 0xAA);
275                 glRectf(x,      y-CHANNELHEIGHT/2,      (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
276
277                 glColor3ub(0, 0, 0);
278
279                 glRasterPos2f(x+8,      y-4);
280                 kb = kb->next;
281                 /* Blender now has support for named
282                  * key blocks. If a name hasn't
283                  * been set for an key block then
284                  * just display the key number -- 
285                  * otherwise display the name stored
286                  * in the keyblock.
287                  */
288                 if (kb->name[0] == '\0') {
289                   sprintf(keyname, "Key %d", i);
290                   BMF_DrawString(G.font, keyname);
291                 }
292                 else {
293                   BMF_DrawString(G.font, kb->name);
294                 }
295
296                 y-=CHANNELHEIGHT+CHANNELSKIP;
297
298         }
299 }
300
301 static void draw_channel_names(void) 
302 {
303         short ofsx, ofsy = 0; 
304         float y;
305         bAction *act;
306         Key *key;
307
308         myortho2                (0,     NAMEWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);   //      Scaling
309
310         /* Blank out the area */
311         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
312                 if(G.v2d->scroll) {     
313                         ofsx= curarea->winrct.xmin;     
314                         ofsy= curarea->winrct.ymin;
315                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin-SCROLLB, NAMEWIDTH, 
316                                            (ofsy+G.v2d->mask.ymax) -
317                                            (ofsy+G.v2d->mask.ymin-SCROLLB)); 
318                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin-SCROLLB, NAMEWIDTH, 
319                                           (ofsy+G.v2d->mask.ymax) -
320                                           (ofsy+G.v2d->mask.ymin-SCROLLB));
321                 }
322         }
323         
324         glClearColor(.8, .8, .8, 0.0); 
325         glClear(GL_COLOR_BUFFER_BIT);
326
327         /* Clip to the scrollable area */
328
329         glColor3ub(0x00, 0x00, 0x00);
330
331         act=G.saction->action;
332         
333         
334         if (act) {
335                 /* if there is a selected action then
336                  * draw the channel names
337                  */
338                 draw_action_channel_names(act);
339         }
340         else {
341             if ( (key = get_action_mesh_key()) ) {
342             /* if there is a mesh selected with rvk's,
343              * then draw the RVK names
344              */
345             draw_action_mesh_names(key);
346         }
347     }
348
349     myortho2 (0,        NAMEWIDTH, 0, 
350               (ofsy+G.v2d->mask.ymax) -
351               (ofsy+G.v2d->mask.ymin-SCROLLB)); //      Scaling
352
353     glShadeModel(GL_SMOOTH);
354  
355     y=9;
356
357     /* Draw sexy shaded block thingies
358            Reevan: if you start developing this stuff again
359            you can have your blend's back
360            
361     glEnable (GL_BLEND);
362     glBegin(GL_QUAD_STRIP);
363     glColor4ub (0xCC,0xCC,0xCC,0x00);
364     glVertex2f (0,SCROLLB*2-y);
365     glVertex2f (NAMEWIDTH,SCROLLB*2-y);
366
367     glColor4ub (0xCC,0xCC,0xCC,0xFF);
368     glVertex2f (0,SCROLLB-y);
369     glVertex2f (NAMEWIDTH,SCROLLB-y);
370
371     glColor4ub (0xCC,0xCC,0xCC,0xFF);
372     glVertex2f (0,0-y);
373     glVertex2f (NAMEWIDTH,0-y);
374
375     glEnd();
376         */
377
378     /*  y=( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB);
379
380         glBegin(GL_QUAD_STRIP);
381         glColor4ub (0x88,0x88,0x88,0xFF);
382         glVertex2f (0,y);
383         glVertex2f (NAMEWIDTH,y);
384         glColor4ub (0x88,0x88,0x88,0x00);
385         glVertex2f (0,y-SCROLLB);
386         glVertex2f (NAMEWIDTH,y-SCROLLB);
387         
388         glEnd();
389     */
390     glDisable (GL_BLEND);
391
392     glShadeModel(GL_FLAT);
393
394 }
395
396 int count_action_levels(bAction *act)
397 {
398         int y=0;
399         bActionChannel *achan;
400
401         if (!act)
402                 return 0;
403
404         for (achan=act->chanbase.first; achan; achan=achan->next){
405                 y+=1;
406                 y+=BLI_countlist(&achan->constraintChannels);
407         }
408
409         return y;
410 }
411         /** Draw a nicely beveled button (in screen space) */
412 void draw_bevel_but(int x, int y, int w, int h, int sel)
413 {
414         int xmin= x, ymin= y;
415         int xmax= x+w-1, ymax= y+h-1;
416         int i;
417
418         glColor3ub(0,0,0);
419         glBegin(GL_LINE_LOOP);
420         glVertex2i(xmin, ymin);
421         glVertex2i(xmax, ymin);
422         glVertex2i(xmax, ymax);
423         glVertex2i(xmin, ymax);
424         glEnd();
425
426         glBegin(GL_LINE_LOOP);
427         if (sel) glColor3ub(0xD0, 0x7E, 0x06);
428         else glColor3ub(0x8C, 0x8C, 0x8C);
429         glVertex2i(xmax-1, ymin+1);
430         glVertex2i(xmax-1, ymax-1);
431         if (sel) glColor3ub(0xF4, 0xEE, 0x8E);
432         else glColor3ub(0xDF, 0xDF, 0xDF);
433         glVertex2i(xmin+1, ymax-1);
434         glVertex2i(xmin+1, ymin+1);
435         glEnd();
436
437         if (sel) glColor3ub(0xF1, 0xCA, 0x13);
438         else glColor3ub(0xAC, 0xAC, 0xAC);
439         glBegin(GL_LINES);
440         for (i=xmin+2; i<=xmax-2; i++) {
441                 glVertex2f(i, ymin+2);
442                 glVertex2f(i, ymax-1);
443         }
444         glEnd();
445 }
446
447 static void draw_channel_strips(SpaceAction *saction)
448 {
449         rcti scr_rct;
450         gla2DDrawInfo *di;
451         bAction *act;
452         bActionChannel *chan;
453         bConstraintChannel *conchan;
454         float   y;
455
456         act= saction->action;
457         if (!act)
458                 return;
459
460         scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
461         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin-SCROLLB;
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         y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
467
468         for (chan=act->chanbase.first; chan; chan=chan->next){
469                 int frame1_x, channel_y;
470
471                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
472
473                 glEnable(GL_BLEND);
474                 if (chan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x22);
475                 else glColor4b(0x55, 0x22, 0x11, 0x22);
476                 glRectf(0,  channel_y-CHANNELHEIGHT/2,  frame1_x,  channel_y+CHANNELHEIGHT/2);
477
478                 if (chan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x44);
479                 else glColor4b(0x55, 0x22, 0x11, 0x44);
480                 glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
481                 glDisable(GL_BLEND);
482         
483                 draw_ipo_channel(di, chan->ipo, 0, y);
484
485                 /*      Increment the step */
486                 y-=CHANNELHEIGHT+CHANNELSKIP;
487
488
489                 /* Draw constraint channels */
490                 for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
491                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
492                         glEnable(GL_BLEND);
493                         if (conchan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x22);
494                         else glColor4b(0x55, 0x22, 0x11, 0x22);
495                         glRectf(0,  channel_y-CHANNELHEIGHT/2+4,  frame1_x,  channel_y+CHANNELHEIGHT/2-4);
496                         
497                         if (conchan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x44);
498                         else glColor4b(0x55, 0x22, 0x11, 0x44);
499                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
500                         glDisable(GL_BLEND);
501                         
502                         draw_ipo_channel(di, conchan->ipo, 0, y);
503                         y-=CHANNELHEIGHT+CHANNELSKIP;
504                 }
505         }
506
507         glaEnd2DDraw(di);
508 }
509
510 static void draw_mesh_strips(SpaceAction *saction, Key *key)
511 {
512         /* draw the RVK keyframes as those little square button things
513          */
514         rcti scr_rct;
515         gla2DDrawInfo *di;
516         float   y, ybase;
517         IpoCurve *icu;
518
519         if (!key->ipo) return;
520
521         scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
522         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin-SCROLLB;
523         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
524         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
525         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
526
527         ybase = key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
528
529         for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
530
531                 int frame1_x, channel_y;
532
533                 /* lets not deal with the "speed" Ipo
534                  */
535                 if (icu->adrcode==0) continue;
536
537                 y = ybase       - (CHANNELHEIGHT+CHANNELSKIP)*(icu->adrcode-1);
538                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
539
540                 /* all frames that have a frame number less than one
541                  * get a desaturated orange background
542                  */
543                 glEnable(GL_BLEND);
544                 glColor4b(0x55, 0x22, 0x11, 0x22);
545                 glRectf(0,        channel_y-CHANNELHEIGHT/2,  
546                                 frame1_x, channel_y+CHANNELHEIGHT/2);
547
548                 /* frames one and higher get a saturated orange background
549                  */
550                 glColor4b(0x55, 0x22, 0x11, 0x44);
551                 glRectf(frame1_x,         channel_y-CHANNELHEIGHT/2,  
552                                 G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
553                 glDisable(GL_BLEND);
554
555                 /* draw the little squares
556                  */
557                 draw_icu_channel(di, icu, 0, y); 
558         }
559
560         glaEnd2DDraw(di);
561 }
562
563 void drawactionspace(ScrArea *sa, void *spacedata)
564 {
565
566         short ofsx = 0, ofsy = 0;
567         Key *key;
568         short maxymin;
569
570         if (!G.saction)
571                 return;
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(G.v2d, curarea->winx, curarea->winy);
604
605         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
606                 if(G.v2d->scroll) {     
607                         ofsx= curarea->winrct.xmin;     
608                         ofsy= curarea->winrct.ymin;
609                         glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
610                                            ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
611                                            ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
612                         glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
613                                           ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
614                                           ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
615                 }
616         }
617
618         glClearColor(.45, .45, .45, 0.0); 
619         glClear(GL_COLOR_BUFFER_BIT);
620
621         myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, 
622                           G.v2d->cur.ymin, G.v2d->cur.ymax);
623
624         /*      Draw backdrop */
625         calc_ipogrid(); 
626         draw_ipogrid();
627
628         /* Draw channel strips */
629         draw_channel_strips(G.saction);
630
631         if (key) {
632                 /* if there is a mesh with rvk's selected,
633                  * then draw the key frames in the action window
634                  */
635                 draw_mesh_strips(G.saction, key);
636                 /*meshactionbuts(G.saction, key);*/
637         }
638
639
640         /* Draw current frame */
641         glViewport(ofsx+G.v2d->mask.xmin,  
642              ofsy+G.v2d->mask.ymin, 
643              ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
644              ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
645         glScissor(ofsx+G.v2d->mask.xmin,  
646             ofsy+G.v2d->mask.ymin, 
647             ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
648             ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
649         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, 
650            G.v2d->cur.ymin, G.v2d->cur.ymax);
651         draw_cfra_action();
652
653         /* Draw scroll */
654         mywinset(curarea->win);
655         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
656       myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
657       if(G.v2d->scroll) drawscroll(0);
658         }
659
660         /* Draw channel names */
661         draw_channel_names();
662
663         if ( key ) {
664                 /* if there is a mesh with rvk's selected,
665                  * then draw the key frames in the action window
666                  */
667                 meshactionbuts(G.saction, key);
668         }
669
670         curarea->win_swap= WIN_BACK_OK;
671 }
672
673
674 void draw_channel_name(const char* name, short type, float ypos, int selected)
675 {
676 }
677
678 static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos)
679 {
680         int v;
681
682         if (!blist)
683                 return;
684
685         for (v = 0; v<totvert; v++){
686                 if (v==0 || (blist[v]->vec[1][0] != blist[v-1]->vec[1][0])){
687                         int sc_x, sc_y;
688                         gla2DDrawTranslatePt(di, blist[v]->vec[1][0], ypos, &sc_x, &sc_y);
689                         draw_bevel_but(sc_x-2, sc_y-5, 7, 13, (blist[v]->f2 & 1));
690                 }
691         }                       
692 }
693
694 void draw_object_channel(gla2DDrawInfo *di, Object *ob, int flags, float ypos)
695 {
696         BezTriple **blist;
697         int totvert;
698
699         blist = ob_to_keylist(ob, flags, &totvert);
700         if (blist){
701                 draw_keylist(di,totvert, blist, ypos);
702                 MEM_freeN(blist);
703         }
704 }
705
706 void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, int flags, float ypos)
707 {
708         BezTriple **blist;
709         int totvert;
710
711         blist = ipo_to_keylist(ipo, flags, &totvert);
712         if (blist){
713                 draw_keylist(di,totvert, blist, ypos);
714                 MEM_freeN(blist);
715         }
716 }
717
718 void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, int flags, float ypos)
719 {
720         /* draw the keys for an IpoCurve
721          */
722         BezTriple **blist;
723         int totvert;
724
725         blist = icu_to_keylist(icu, flags, &totvert);
726         if (blist){
727                 draw_keylist(di,totvert, blist, ypos);
728                 MEM_freeN(blist);
729         }
730 }
731
732 void draw_action_channel(gla2DDrawInfo *di, bAction *act, int flags, float ypos)
733 {
734         BezTriple **blist;
735         int totvert;
736
737         blist = action_to_keylist(act, flags, &totvert);
738         if (blist){
739                 draw_keylist(di,totvert, blist, ypos);
740                 MEM_freeN(blist);
741         }
742 }
743
744 static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert)
745 {
746         IpoCurve *icu;
747         int v, count=0;
748
749         BezTriple **list = NULL;
750
751         if (ob){
752
753                 /* Count Object Keys */
754                 if (ob->ipo){
755                         for (icu=ob->ipo->curve.first; icu; icu=icu->next){
756                                 count+=icu->totvert;
757                         }
758                 }
759                 
760                 /* Count Constraint Keys */
761                 /* Count object data keys */
762
763                 /* Build the list */
764                 if (count){
765                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
766                         count=0;
767                         
768                         /* Add object keyframes */
769                         for (icu=ob->ipo->curve.first; icu; icu=icu->next){
770                                 for (v=0; v<icu->totvert; v++){
771                                         list[count++]=&icu->bezt[v];
772                                 }
773                         }
774                         
775                         /* Add constraint keyframes */
776                         /* Add object data keyframes */
777
778                         /* Sort */
779                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
780                 }
781         }
782         (*totvert)=count;
783         return list;
784 }
785
786 static BezTriple **icu_to_keylist(IpoCurve *icu, int flags, int *totvert)
787 {
788         /* compile a list of all bezier triples in an
789          * IpoCurve.
790          */
791         int v, count = 0;
792
793         BezTriple **list = NULL;
794
795         count=icu->totvert;
796
797         if (count){
798                 list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
799                 count=0;
800                         
801                 for (v=0; v<icu->totvert; v++){
802                         list[count++]=&icu->bezt[v];
803                 }
804                 qsort(list, count, sizeof(BezTriple*), bezt_compare);
805         }
806         (*totvert)=count;
807         return list;
808
809 }
810
811 static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert)
812 {
813         IpoCurve *icu;
814         int v, count=0;
815
816         BezTriple **list = NULL;
817
818         if (ipo){
819                 /* Count required keys */
820                 for (icu=ipo->curve.first; icu; icu=icu->next){
821                         count+=icu->totvert;
822                 }
823                 
824                 /* Build the list */
825                 if (count){
826                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
827                         count=0;
828                         
829                         for (icu=ipo->curve.first; icu; icu=icu->next){
830                                 for (v=0; v<icu->totvert; v++){
831                                         list[count++]=&icu->bezt[v];
832                                 }
833                         }                       
834                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
835                 }
836         }
837         (*totvert)=count;
838         return list;
839 }
840
841 static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert)
842 {
843         IpoCurve *icu;
844         bActionChannel *achan;
845         bConstraintChannel *conchan;
846         int v, count=0;
847
848         BezTriple **list = NULL;
849
850         if (act){
851                 /* Count required keys */
852                 for (achan=act->chanbase.first; achan; achan=achan->next){
853                         /* Count transformation keys */
854                         for (icu=achan->ipo->curve.first; icu; icu=icu->next)
855                                 count+=icu->totvert;
856                         
857                         /* Count constraint keys */
858                         for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
859                                 for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
860                                         count+=icu->totvert;
861                         
862
863                 }
864                 
865                 /* Build the list */
866                 if (count){
867                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
868                         count=0;
869                         
870                         for (achan=act->chanbase.first; achan; achan=achan->next){
871                                 /* Add transformation keys */
872                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next){
873                                         for (v=0; v<icu->totvert; v++)
874                                                 list[count++]=&icu->bezt[v];
875                                 }
876                                         
877                                         /* Add constraint keys */
878                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){
879                                         for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
880                                                 for (v=0; v<icu->totvert; v++)
881                                                         list[count++]=&icu->bezt[v];
882                                 }
883                                                         
884                         }               
885                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
886                         
887                 }
888         }
889         (*totvert)=count;
890         return list;
891 }
892