f1aba5903586dd7173f1768a43941f5aa928af00
[blender-staging.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_listBase.h"
52 #include "DNA_action_types.h"
53 #include "DNA_armature_types.h"
54 #include "DNA_curve_types.h"
55 #include "DNA_ipo_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_screen_types.h"
58 #include "DNA_scene_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_constraint_types.h"
61 #include "DNA_key_types.h"
62
63 #include "BKE_action.h"
64 #include "BKE_ipo.h"
65 #include "BKE_global.h"
66 #include "BKE_utildefines.h"
67
68 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
69
70 #include "BIF_editaction.h"
71 #include "BIF_editkey.h"
72 #include "BIF_interface.h"
73 #include "BIF_interface_icons.h"
74 #include "BIF_gl.h"
75 #include "BIF_glutil.h"
76 #include "BIF_resources.h"
77 #include "BIF_screen.h"
78 #include "BIF_mywindow.h"
79 #include "BIF_space.h"
80
81 #include "BDR_drawaction.h"
82 #include "BDR_editcurve.h"
83
84 #include "BSE_drawnla.h"
85 #include "BSE_drawipo.h"
86 #include "BSE_editipo.h"
87 #include "BSE_time.h"
88 #include "BSE_view.h"
89
90 /* 'old' stuff": defines and types, and own include -------------------- */
91
92 #include "blendef.h"
93 #include "mydevice.h"
94
95 /* sliders for shapekeys */
96 static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key)
97 {
98         int           i;
99         char          str[64];
100         float           x, y;
101         uiBlock       *block;
102         uiBut             *but;
103
104 #define XIC 20
105 #define YIC 20
106
107         /* lets make the rvk sliders */
108
109         /* reset the damn myortho2 or the sliders won't draw/redraw
110          * correctly *grumble*
111          */
112         mywinset(curarea->win);
113         myortho2(-0.375, curarea->winx-0.375, G.v2d->cur.ymin, G.v2d->cur.ymax);
114
115     sprintf(str, "actionbuttonswin %d", curarea->win);
116     block= uiNewBlock (&curarea->uiblocks, str, 
117                        UI_EMBOSS, UI_HELV, curarea->win);
118
119         x = NAMEWIDTH + 1;
120     y = CHANNELHEIGHT/2;
121
122         /* make the little 'open the sliders' widget */
123     BIF_ThemeColor(TH_FACE); // this slot was open...
124         glRects(2,            y + 2*CHANNELHEIGHT - 2,  
125                         ACTWIDTH - 2, y + CHANNELHEIGHT + 2);
126         glColor3ub(0, 0, 0);
127         glRasterPos2f(4, y + CHANNELHEIGHT + 6);
128         BMF_DrawString(G.font, "Sliders");
129
130         uiBlockSetEmboss(block, UI_EMBOSSN);
131
132         if (!(G.saction->flag & SACTION_SLIDERS)) {
133                 ACTWIDTH = NAMEWIDTH;
134                 but=uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR, 
135                                           ICON_DISCLOSURE_TRI_RIGHT,
136                                           NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
137                                           XIC,YIC-2,
138                                           &(G.saction->flag), 0, 0, 0, 0, 
139                                           "Show action window sliders");
140                 /* no hilite, the winmatrix is not correct later on... */
141                 uiButSetFlag(but, UI_NO_HILITE);
142
143         }
144         else {
145                 but= uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR, 
146                                           ICON_DISCLOSURE_TRI_DOWN,
147                                           NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
148                                           XIC,YIC-2,
149                                           &(G.saction->flag), 0, 0, 0, 0, 
150                                           "Hide action window sliders");
151                 /* no hilite, the winmatrix is not correct later on... */
152                 uiButSetFlag(but, UI_NO_HILITE);
153                                           
154                 ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
155
156                 /* sliders are open so draw them */
157                 BIF_ThemeColor(TH_FACE); 
158
159                 glRects(NAMEWIDTH,  0,  NAMEWIDTH+SLIDERWIDTH,  curarea->winy);
160                 uiBlockSetEmboss(block, UI_EMBOSS);
161                 for (i=1 ; i < key->totkey ; ++ i) {
162                         make_rvk_slider(block, ob, i, 
163                                                         x, y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
164
165                         y-=CHANNELHEIGHT+CHANNELSKIP;
166                         
167                         /* see sliderval array in editkey.c */
168                         if(i>=255) break;
169                 }
170         }
171         uiDrawBlock(block);
172
173 }
174
175 static void icu_slider_func(void *voidicu, void *voidignore) 
176 {
177         /* the callback for the icu sliders ... copies the
178          * value from the icu->curval into a bezier at the
179          * right frame on the right ipo curve (creating both the
180          * ipo curve and the bezier if needed).
181          */
182         IpoCurve  *icu= voidicu;
183         BezTriple *bezt=NULL;
184         float cfra, icuval;
185
186         cfra = frame_to_float(CFRA);
187         if (G.saction->pin==0 && OBACT)
188                 cfra= get_action_frame(OBACT, cfra);
189         
190         /* if the ipocurve exists, try to get a bezier
191          * for this frame
192          */
193         bezt = get_bezt_icu_time(icu, &cfra, &icuval);
194
195         /* create the bezier triple if one doesn't exist,
196          * otherwise modify it's value
197          */
198         if (!bezt) {
199                 insert_vert_ipo(icu, cfra, icu->curval);
200         }
201         else {
202                 bezt->vec[1][1] = icu->curval;
203         }
204
205         /* make sure the Ipo's are properly process and
206          * redraw as necessary
207          */
208         sort_time_ipocurve(icu);
209         testhandles_ipocurve(icu);
210         
211         allqueue (REDRAWVIEW3D, 0);
212         allqueue (REDRAWACTION, 0);
213         allqueue (REDRAWNLA, 0);
214         allqueue (REDRAWIPO, 0);
215         allspace(REMAKEIPO, 0);
216         allqueue(REDRAWBUTSALL, 0);
217 }
218
219 static void make_icu_slider(uiBlock *block, IpoCurve *icu,
220                                          int x, int y, int w, int h, char *tip)
221 {
222         /* create a slider for the ipo-curve*/
223         uiBut *but;
224         
225         if(icu==NULL) return;
226         
227         if (IS_EQ(icu->slide_max, icu->slide_min)) {
228                 if (IS_EQ(icu->ymax, icu->ymin)) {
229                         if (icu->blocktype == ID_CO) {
230                                 /* hack for constraints (and maybe a few others) */
231                                 icu->slide_min= 0.0;
232                                 icu->slide_max= 1.0;
233                         }
234                         else {
235                                 icu->slide_min= -100;
236                                 icu->slide_max= 100;
237                         }
238                 }
239                 else {
240                         icu->slide_min= icu->ymin;
241                         icu->slide_max= icu->ymax;
242                 }
243         }
244         if (icu->slide_min >= icu->slide_max) {
245                 SWAP(float, icu->slide_min, icu->slide_max);
246         }
247
248         but=uiDefButF(block, NUMSLI, REDRAWVIEW3D, "",
249                                   x, y , w, h,
250                                   &(icu->curval), icu->slide_min, icu->slide_max, 
251                                   10, 2, tip);
252         
253         uiButSetFunc(but, icu_slider_func, icu, NULL);
254         
255         // no hilite, the winmatrix is not correct later on...
256         uiButSetFlag(but, UI_NO_HILITE);
257 }
258
259 /* sliders for ipo-curves of active action-channel */
260 static void action_icu_buts(SpaceAction *saction)
261 {
262         bAction *act= saction->action;
263         bActionChannel *achan;
264         bConstraintChannel *conchan;
265         IpoCurve *icu;
266         char          str[64];
267         float           x, y;
268         uiBlock       *block;
269
270         /* lets make the action sliders */
271
272         /* reset the damn myortho2 or the sliders won't draw/redraw
273          * correctly *grumble*
274          */
275         mywinset(curarea->win);
276         myortho2(-0.375, curarea->winx-0.375, G.v2d->cur.ymin, G.v2d->cur.ymax);
277         
278     sprintf(str, "actionbuttonswin %d", curarea->win);
279     block= uiNewBlock (&curarea->uiblocks, str, 
280                        UI_EMBOSS, UI_HELV, curarea->win);
281
282         x = NAMEWIDTH + 1;
283     y = 0.0;
284         
285         uiBlockSetEmboss(block, UI_EMBOSSN);
286
287         if (G.saction->flag & SACTION_SLIDERS) {
288                 /* sliders are open so draw them */
289                 
290                 /* draw backdrop first */
291                 BIF_ThemeColor(TH_FACE); // change this color... it's ugly
292                 glRects(NAMEWIDTH,  G.v2d->cur.ymin,  NAMEWIDTH+SLIDERWIDTH,  G.v2d->cur.ymax);
293                 
294                 uiBlockSetEmboss(block, UI_EMBOSS);
295                 for (achan=act->chanbase.first; achan; achan= achan->next) {
296                         if(VISIBLE_ACHAN(achan)) {
297                                 y-=CHANNELHEIGHT+CHANNELSKIP;
298                                 
299                                 if (EXPANDED_ACHAN(achan)) {                                    
300                                         if (achan->ipo) {
301                                                 y-=CHANNELHEIGHT+CHANNELSKIP;
302                                                 
303                                                 if (FILTER_IPO_ACHAN(achan)) {
304                                                         for (icu= achan->ipo->curve.first; icu; icu=icu->next) {
305                                                                 if (achan->flag & ACHAN_HILIGHTED) {
306                                                                         make_icu_slider(block, icu,
307                                                                                                         x, y, SLIDERWIDTH-2, CHANNELHEIGHT-2, 
308                                                                                                         "Slider to control current value of IPO-Curve");
309                                                                 }
310                                                                 
311                                                                 y-=CHANNELHEIGHT+CHANNELSKIP;
312                                                         }
313                                                 }
314                                         }
315                                         
316                                         if (achan->constraintChannels.first) {
317                                                 y-=CHANNELHEIGHT+CHANNELSKIP;
318                                                 
319                                                 if (FILTER_CON_ACHAN(achan)) {
320                                                         for (conchan= achan->constraintChannels.first; conchan; conchan=conchan->next) {
321                                                                 if ((achan->flag & ACHAN_HILIGHTED) && EDITABLE_CONCHAN(conchan)) {
322                                                                         icu= (IpoCurve *)conchan->ipo->curve.first;
323                                                                         make_icu_slider(block, icu,
324                                                                                                         x, y, SLIDERWIDTH-2, CHANNELHEIGHT-2, 
325                                                                                                         "Slider to control current value of Constraint Channel");
326                                                                 }
327                                                                 
328                                                                 y-=CHANNELHEIGHT+CHANNELSKIP;
329                                                         }
330                                                 }
331                                         }
332                                 }
333                         }
334                 }
335         }
336         uiDrawBlock(block);
337 }
338
339 void draw_cfra_action(void)
340 {
341         Object *ob;
342         float vec[2];
343         
344         vec[0]= (G.scene->r.cfra);
345         vec[0]*= G.scene->r.framelen;
346         
347         vec[1]= G.v2d->cur.ymin;
348         glColor3ub(0x60, 0xc0, 0x40);
349         glLineWidth(2.0);
350         
351         glBegin(GL_LINE_STRIP);
352         glVertex2fv(vec);
353         vec[1]= G.v2d->cur.ymax;
354         glVertex2fv(vec);
355         glEnd();
356         
357         ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
358         if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
359                 vec[0]-= ob->sf;
360                 
361                 glColor3ub(0x10, 0x60, 0);
362                 
363                 glBegin(GL_LINE_STRIP);
364                 glVertex2fv(vec);
365                 vec[1]= G.v2d->cur.ymin;
366                 glVertex2fv(vec);
367                 glEnd();
368         }
369         
370         glLineWidth(1.0);
371 }
372
373 /* left hand */
374 static void draw_action_channel_names(bAction *act) 
375 {
376     bActionChannel *achan;
377     bConstraintChannel *conchan;
378         IpoCurve *icu;
379     float       x, y;
380
381     x = 0.0;
382         y = 0.0f;
383
384         for (achan=act->chanbase.first; achan; achan= achan->next) {
385                 if(VISIBLE_ACHAN(achan)) {
386                         glEnable(GL_BLEND);
387                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
388                         
389                         /* draw backing strip behind action channel name */
390                         BIF_ThemeColorShade(TH_HEADER, 20);
391                         glRectf(x,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
392                         
393                         /* draw expand/collapse triangle for action-channel */
394                         if (EXPANDED_ACHAN(achan))
395                                 BIF_icon_draw(x+1, y-CHANNELHEIGHT/2, ICON_TRIA_DOWN);
396                         else
397                                 BIF_icon_draw(x+1, y-CHANNELHEIGHT/2, ICON_TRIA_RIGHT);
398                         
399                         /* draw name of action channel */
400                         if (SEL_ACHAN(achan))
401                                 BIF_ThemeColor(TH_TEXT_HI);
402                         else
403                                 BIF_ThemeColor(TH_TEXT);
404                         glRasterPos2f(x+18,  y-4);
405                         BMF_DrawString(G.font, achan->name);
406                         
407                         /* draw 'lock' indicating whether channel is protected */
408                         if (EDITABLE_ACHAN(achan)==0) 
409                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
410                         else 
411                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);
412                         y-=CHANNELHEIGHT+CHANNELSKIP;
413                         
414                         if (EXPANDED_ACHAN(achan)) {
415                                 /* Draw IPO-curves show/hide widget */
416                                 if (achan->ipo) {                                       
417                                         /* draw backing strip behind */
418                                         BIF_ThemeColorShade(TH_HEADER, -20);
419                                         glRectf(x+7,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
420                                         
421                                         /* draw expand/collapse triangle for showing sub-channels  */
422                                         if (FILTER_IPO_ACHAN(achan))
423                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_DOWN);
424                                         else
425                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_RIGHT);
426                                         
427                                         /* draw icon showing type of ipo-block */
428                                         BIF_icon_draw(x+24, y-CHANNELHEIGHT/2, geticon_ipo_blocktype(achan->ipo->blocktype));
429                                         
430                                         /* draw name of ipo-block */
431                                         if (SEL_ACHAN(achan))
432                                                 BIF_ThemeColor(TH_TEXT_HI);
433                                         else
434                                                 BIF_ThemeColor(TH_TEXT);
435                                         glRasterPos2f(x+40,  y-4);
436                                         BMF_DrawString(G.font, "IPO Curves"); // TODO: make proper naming scheme
437                                 
438                                         y-=CHANNELHEIGHT+CHANNELSKIP;
439                                 
440                                         /* Draw IPO-curve-channels? */
441                                         if (FILTER_IPO_ACHAN(achan)) {
442                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
443                                                         char *icu_name= getname_ipocurve(icu);
444                                                         
445                                                         /* draw backing strip behind ipo-curve channel*/
446                                                         BIF_ThemeColorShade(TH_HEADER, -40);
447                                                         glRectf(x+14,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
448                                                         
449                                                         /* draw name of ipo-curve channel */
450                                                         if (SEL_ICU(icu))
451                                                                 BIF_ThemeColor(TH_TEXT_HI);
452                                                         else
453                                                                 BIF_ThemeColor(TH_TEXT);
454                                                         glRasterPos2f(x+24,  y-4);
455                                                         BMF_DrawString(G.font, icu_name);
456                                                         
457 #if 0 /* tempolarily disabled until all ipo-code can support this option */
458                                                         /* draw 'lock' to indicate if ipo-curve channel is protected */
459                                                         if (EDITABLE_ICU(icu)==0) 
460                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
461                                                         else 
462                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);  
463 #endif
464                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
465                                                 }
466                                         }
467                                 }
468
469                                 /* Draw constraints show/hide widget */
470                                 if (achan->constraintChannels.first) {
471                                         /* draw backing strip behind */
472                                         BIF_ThemeColorShade(TH_HEADER, -20);
473                                         glRectf(x+7,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
474                                         
475                                         /* draw expand/collapse triangle for showing sub-channels  */
476                                         if (FILTER_CON_ACHAN(achan))
477                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_DOWN);
478                                         else
479                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_RIGHT);
480                                         
481                                         /* draw constraint icon */
482                                         BIF_icon_draw(x+24, y-CHANNELHEIGHT/2, ICON_CONSTRAINT);
483                                         
484                                         /* draw name of widget */
485                                         if (SEL_ACHAN(achan))
486                                                 BIF_ThemeColor(TH_TEXT_HI);
487                                         else
488                                                 BIF_ThemeColor(TH_TEXT);
489                                         glRasterPos2f(x+40,  y-4);
490                                         BMF_DrawString(G.font, "Constraints");
491                                 
492                                         y-=CHANNELHEIGHT+CHANNELSKIP;
493                                 
494                                         /* Draw constraint channels?  */
495                                         if (FILTER_CON_ACHAN(achan)) {
496                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
497                                                         /* draw backing strip behind constraint channel*/
498                                                         BIF_ThemeColorShade(TH_HEADER, -40);
499                                                         glRectf(x+14,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
500                                                         
501                                                         /* draw name of constraint channel */
502                                                         if (SEL_CONCHAN(conchan))
503                                                                 BIF_ThemeColor(TH_TEXT_HI);
504                                                         else
505                                                                 BIF_ThemeColor(TH_TEXT);
506                                                         glRasterPos2f(x+25,  y-4);
507                                                         BMF_DrawString(G.font, conchan->name);
508                                                         
509                                                         /* draw 'lock' to indicate if constraint channel is protected */
510                                                         if (EDITABLE_CONCHAN(conchan)==0) 
511                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
512                                                         else 
513                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);  
514                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
515                                                 }
516                                         }
517                                 }
518                         }
519                         
520                         glDisable(GL_BLEND);
521                 }
522         }
523 }
524
525
526 static void draw_action_mesh_names(Key *key) 
527 {
528         /* draws the names of the rvk keys in the
529          * left side of the action window
530          */
531         int          i;
532         char     keyname[32];
533         float    x, y;
534         KeyBlock *kb;
535
536         x = 0.0;
537         y= 0.0;
538
539         kb= key->block.first;
540
541         for (i=1 ; i < key->totkey ; ++ i) {
542                 glColor3ub(0xAA, 0xAA, 0xAA);
543                 glRectf(x,      y-CHANNELHEIGHT/2,      (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
544
545                 glColor3ub(0, 0, 0);
546
547                 glRasterPos2f(x+8,      y-4);
548                 kb = kb->next;
549                 /* Blender now has support for named
550                  * key blocks. If a name hasn't
551                  * been set for an key block then
552                  * just display the key number -- 
553                  * otherwise display the name stored
554                  * in the keyblock.
555                  */
556                 if (kb->name[0] == '\0') {
557                   sprintf(keyname, "Key %d", i);
558                   BMF_DrawString(G.font, keyname);
559                 }
560                 else {
561                   BMF_DrawString(G.font, kb->name);
562                 }
563
564                 y-=CHANNELHEIGHT+CHANNELSKIP;
565
566         }
567 }
568
569 /* left hand part */
570 static void draw_channel_names(void) 
571 {
572         short ofsx, ofsy = 0; 
573         bAction *act;
574         Key *key;
575
576         /* Clip to the scrollable area */
577         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
578                 if(G.v2d->scroll) {     
579                         ofsx= curarea->winrct.xmin;     
580                         ofsy= curarea->winrct.ymin;
581                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
582                                            (ofsy+G.v2d->mask.ymax) -
583                                            (ofsy+G.v2d->mask.ymin)); 
584                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
585                                           (ofsy+G.v2d->mask.ymax) -
586                                           (ofsy+G.v2d->mask.ymin));
587                 }
588         }
589         
590         myortho2(0,     NAMEWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);   //      Scaling
591         
592         glColor3ub(0x00, 0x00, 0x00);
593
594         act=G.saction->action;
595
596         if (act) {
597                 /* if there is a selected action then
598                  * draw the channel names
599                  */
600                 draw_action_channel_names(act);
601         }
602         else if ( (key = get_action_mesh_key()) ) {
603                 /* if there is a mesh selected with rvk's,
604                  * then draw the RVK names
605                  */
606                 draw_action_mesh_names(key);
607     }
608
609     myortho2(0, NAMEWIDTH, 0, (ofsy+G.v2d->mask.ymax) -
610               (ofsy+G.v2d->mask.ymin)); //      Scaling
611
612 }
613
614 int count_action_levels(bAction *act)
615 {
616         bActionChannel *achan;
617         int y=0;
618
619         if (!act) 
620                 return 0;
621
622         for (achan=act->chanbase.first; achan; achan=achan->next) {
623                 if(VISIBLE_ACHAN(achan)) {
624                         y++;
625                         
626                         if (EXPANDED_ACHAN(achan)) {
627                                 if (achan->constraintChannels.first) {
628                                         y++;
629                                         if (FILTER_CON_ACHAN(achan))
630                                                 y += BLI_countlist(&achan->constraintChannels);
631                                 }
632                                 else if (achan->ipo) {
633                                         y++;
634                                         if (FILTER_IPO_ACHAN(achan))
635                                                 y += BLI_countlist(&achan->ipo->curve);
636                                 }
637                         }
638                 }
639         }
640
641         return y;
642 }
643
644 /* sets or clears hidden flags */
645 void check_action_context(SpaceAction *saction)
646 {
647         bActionChannel *achan;
648         
649         if(saction->action==NULL) return;
650         
651         for (achan=saction->action->chanbase.first; achan; achan=achan->next)
652                 achan->flag &= ~ACHAN_HIDDEN;
653         
654         if (G.saction->pin==0 && OBACT) {
655                 Object *ob= OBACT;
656                 bPoseChannel *pchan;
657                 bArmature *arm= ob->data;
658                 
659                 for (achan=saction->action->chanbase.first; achan; achan=achan->next) {
660                         pchan= get_pose_channel(ob->pose, achan->name);
661                         if (pchan) {
662                                 if ((pchan->bone->layer & arm->layer)==0)
663                                         achan->flag |= ACHAN_HIDDEN;
664                                 else if (pchan->bone->flag & BONE_HIDDEN_P)
665                                         achan->flag |= ACHAN_HIDDEN;
666                         }
667                 }
668         }
669 }
670
671 static void draw_channel_strips(SpaceAction *saction)
672 {
673         rcti scr_rct;
674         gla2DDrawInfo *di;
675         bAction *act;
676         bActionChannel *achan;
677         bConstraintChannel *conchan;
678         IpoCurve *icu;
679         float y, sta, end;
680         int act_start, act_end, dummy;
681         char col1[3], col2[3];
682         
683         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
684         BIF_GetThemeColor3ubv(TH_HILITE, col1);
685
686         act= saction->action;
687         if (!act)
688                 return;
689
690         scr_rct.xmin= saction->area->winrct.xmin + saction->v2d.mask.xmin;
691         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
692         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
693         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
694         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
695
696         /* if in NLA there's a strip active, map the view */
697         if (G.saction->pin==0 && OBACT)
698                 map_active_strip(di, OBACT, 0);
699         
700         /* start and end of action itself */
701         calc_action_range(act, &sta, &end, 0);
702         gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
703         gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
704         
705         if (G.saction->pin==0 && OBACT)
706                 map_active_strip(di, OBACT, 1);
707         
708         /* first backdrop strips */
709         y = 0.0;
710         glEnable(GL_BLEND);
711         for (achan=act->chanbase.first; achan; achan= achan->next) {
712                 if(VISIBLE_ACHAN(achan)) {
713                         int frame1_x, channel_y;
714                         
715                         gla2DDrawTranslatePt(di, G.v2d->cur.xmin, y, &frame1_x, &channel_y);
716                         
717                         if (SEL_ACHAN(achan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
718                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
719                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
720                         
721                         if (SEL_ACHAN(achan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
722                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
723                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2,  act_end,  channel_y+CHANNELHEIGHT/2);
724                         
725                         /*      Increment the step */
726                         y-=CHANNELHEIGHT+CHANNELSKIP;
727                         
728                         /* Draw sub channels */
729                         if (EXPANDED_ACHAN(achan)) {
730                                 /* Draw ipo channels */
731                                 if (achan->ipo) {
732                                         y-=CHANNELHEIGHT+CHANNELSKIP;
733                                         
734                                         if (FILTER_IPO_ACHAN(achan)) {
735                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
736                                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
737                                                         
738                                                         if (SEL_ICU(icu)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
739                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
740                                                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
741                                                         
742                                                         if (SEL_ICU(icu)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
743                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
744                                                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2+4,  act_end,  channel_y+CHANNELHEIGHT/2-4);
745                                                         
746                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
747                                                 }
748                                         }
749                                 }
750                                 
751                                 /* Draw constraint channels */
752                                 if (achan->constraintChannels.first) {
753                                         y-=CHANNELHEIGHT+CHANNELSKIP;
754                                         
755                                         if (FILTER_CON_ACHAN(achan)) {
756                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
757                                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
758                                                         
759                                                         if (SEL_CONCHAN(conchan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
760                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
761                                                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
762                                                         
763                                                         if (SEL_CONCHAN(conchan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
764                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
765                                                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2+4,  act_end,  channel_y+CHANNELHEIGHT/2-4);
766                                                         
767                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
768                                                 }
769                                         }
770                                 }
771                         }
772                 }
773         }               
774         glDisable(GL_BLEND);
775         
776         if (G.saction->pin==0 && OBACT)
777                 map_active_strip(di, OBACT, 0);
778         
779         /* keyframes  */
780         y = 0.0;
781         for (achan= act->chanbase.first; achan; achan= achan->next) {
782                 if(VISIBLE_ACHAN(achan)) {
783                         
784                         draw_ipo_channel(di, achan->ipo, y);
785                         y-=CHANNELHEIGHT+CHANNELSKIP;
786
787                         /* Draw sub channels */
788                         if (EXPANDED_ACHAN(achan)) {
789                                 /* Draw ipo curves */
790                                 if (achan->ipo) {
791                                         y-=CHANNELHEIGHT+CHANNELSKIP;
792                                         
793                                         if (FILTER_IPO_ACHAN(achan)) {
794                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
795                                                         draw_icu_channel(di, icu, y);
796                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
797                                                 }
798                                         }
799                                 }
800                                 
801                                 /* Draw constraint channels */
802                                 if (achan->constraintChannels.first) {
803                                         y-=CHANNELHEIGHT+CHANNELSKIP;
804                                         
805                                         if (FILTER_CON_ACHAN(achan)) {
806                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
807                                                         draw_ipo_channel(di, conchan->ipo, y);
808                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
809                                                 }
810                                         }
811                                 }
812                         }
813                 }
814         }
815
816         if(saction->flag & SACTION_MOVING) {
817                 int frame1_x, channel_y;
818                 gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &channel_y);
819                 cpack(0x0);
820                 glBegin(GL_LINES);
821                 glVertex2f(frame1_x, G.v2d->mask.ymin - 100);
822                 glVertex2f(frame1_x, G.v2d->mask.ymax);
823                 glEnd();
824         }
825         
826         glaEnd2DDraw(di);
827 }
828
829 static void draw_mesh_strips(SpaceAction *saction, Key *key)
830 {
831         /* draw the RVK keyframes */
832         rcti scr_rct;
833         gla2DDrawInfo *di;
834         float   y, ybase;
835         IpoCurve *icu;
836         char col1[3], col2[3];
837         
838         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
839         BIF_GetThemeColor3ubv(TH_HILITE, col1);
840
841         if (!key->ipo) return;
842
843         scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
844         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
845         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
846         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
847         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
848
849         ybase = 0;
850
851         for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
852                 int frame1_x, channel_y;
853                 
854                 /* lets not deal with the "speed" Ipo */
855                 if (icu->adrcode==0) continue;
856                 
857                 y = ybase       - (CHANNELHEIGHT+CHANNELSKIP)*(icu->adrcode-1);
858                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
859                         
860                 /* all frames that have a frame number less than one
861                  * get a desaturated orange background
862                  */
863                 glEnable(GL_BLEND);
864                 glColor4ub(col2[0], col2[1], col2[2], 0x22);
865                 glRectf(0,        channel_y-CHANNELHEIGHT/2,  
866                                 frame1_x, channel_y+CHANNELHEIGHT/2);
867
868                 /* frames one and higher get a saturated orange background */
869                 glColor4ub(col2[0], col2[1], col2[2], 0x44);
870                 glRectf(frame1_x,         channel_y-CHANNELHEIGHT/2,  
871                                 G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
872                 glDisable(GL_BLEND);
873
874                 /* draw the keyframes */
875                 draw_icu_channel(di, icu, y); 
876         }
877
878         glaEnd2DDraw(di);
879 }
880
881 /* ********* action panel *********** */
882
883
884 void do_actionbuts(unsigned short event)
885 {
886         switch(event) {
887         case REDRAWVIEW3D:
888                 allqueue(REDRAWVIEW3D, 0);
889                 break;
890         case B_REDR:
891                 allqueue(REDRAWACTION, 0);
892                 break;
893         }
894 }
895
896
897 static void action_panel_properties(short cntrl)        // ACTION_HANDLER_PROPERTIES
898 {
899         uiBlock *block;
900
901         block= uiNewBlock(&curarea->uiblocks, "action_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
902         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
903         uiSetPanelHandler(ACTION_HANDLER_PROPERTIES);  // for close and esc
904         if(uiNewPanel(curarea, block, "Transform Properties", "Action", 10, 230, 318, 204)==0) return;
905
906         uiDefBut(block, LABEL, 0, "test text",          10,180,300,19, 0, 0, 0, 0, 0, "");
907
908 }
909
910 static void action_blockhandlers(ScrArea *sa)
911 {
912         SpaceAction *sact= sa->spacedata.first;
913         short a;
914         
915         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
916                 switch(sact->blockhandler[a]) {
917
918                 case ACTION_HANDLER_PROPERTIES:
919                         action_panel_properties(sact->blockhandler[a+1]);
920                         break;
921                 
922                 }
923                 /* clear action value for event */
924                 sact->blockhandler[a+1]= 0;
925         }
926         uiDrawBlocksPanels(sa, 0);
927 }
928
929 /* ************************* Action Editor Space ***************************** */
930
931 void drawactionspace(ScrArea *sa, void *spacedata)
932 {
933         short ofsx = 0, ofsy = 0;
934         bAction *act;
935         Key *key;
936         float col[3];
937         short maxymin;
938
939         if (!G.saction)
940                 return;
941
942         /* warning; blocks need to be freed each time, handlers dont remove  */
943         uiFreeBlocksWin(&sa->uiblocks, sa->win);
944
945         if (!G.saction->pin) {
946                 /* allow more than one active action sometime? */
947                 if (OBACT)
948                         G.saction->action = OBACT->action;
949                 else
950                         G.saction->action=NULL;
951         }
952         key = get_action_mesh_key();
953         act= G.saction->action;
954
955         /* Damn I hate hunting to find my rvk's because
956          * they have scrolled off of the screen ... this
957          * oughta fix it
958          */
959         
960         if (!act && key) {
961                 if (G.v2d->cur.ymin < -CHANNELHEIGHT) 
962                         G.v2d->cur.ymin = -CHANNELHEIGHT;
963                 
964                 maxymin = -(key->totkey*(CHANNELHEIGHT+CHANNELSKIP));
965                 if (G.v2d->cur.ymin > maxymin) G.v2d->cur.ymin = maxymin;
966         }
967
968         /* Lets make sure the width of the left hand of the screen
969          * is set to an appropriate value based on whether sliders
970          * are showing of not
971          */
972         if (((key)||(act)) && (G.saction->flag & SACTION_SLIDERS)) 
973                 ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
974         else 
975                 ACTWIDTH = NAMEWIDTH;
976
977         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
978
979         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
980
981         /* background color for entire window (used in lefthand part tho) */
982         BIF_GetThemeColor3fv(TH_HEADER, col);
983         glClearColor(col[0], col[1], col[2], 0.0); 
984         glClear(GL_COLOR_BUFFER_BIT);
985         
986         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
987                 if(G.v2d->scroll) {     
988                         ofsx= curarea->winrct.xmin;     
989                         ofsy= curarea->winrct.ymin;
990                         glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
991                                            ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
992                                            ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
993                         glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
994                                           ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
995                                           ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
996                 }
997         }
998
999         BIF_GetThemeColor3fv(TH_BACK, col);
1000         glClearColor(col[0], col[1], col[2], 0.0);
1001         glClear(GL_COLOR_BUFFER_BIT);
1002
1003         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
1004         bwin_clear_viewmat(sa->win);    /* clear buttons view */
1005         glLoadIdentity();
1006
1007         /*      Draw backdrop */
1008         calc_ipogrid(); 
1009         draw_ipogrid();
1010
1011         check_action_context(G.saction);
1012         
1013         /* Draw channel strips */
1014         if (act) {
1015                 draw_channel_strips(G.saction);
1016         }
1017         else if (key) {
1018                 /* if there is a mesh with rvk's selected,
1019                  * then draw the key frames in the action window
1020                  */
1021                 draw_mesh_strips(G.saction, key);
1022         }
1023         
1024         /* reset matrices for stuff to be drawn on top of keys*/
1025         glViewport(ofsx+G.v2d->mask.xmin,  
1026              ofsy+G.v2d->mask.ymin, 
1027              ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1028              ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
1029         glScissor(ofsx+G.v2d->mask.xmin,  
1030             ofsy+G.v2d->mask.ymin, 
1031             ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1032             ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
1033         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax,  G.v2d->cur.ymin, G.v2d->cur.ymax);
1034         
1035         /* Draw current frame */
1036         draw_cfra_action();
1037         
1038         /* Draw markers */
1039         draw_markers_timespace();
1040         
1041         /* Draw 'curtains' for preview */
1042         draw_anim_preview_timespace();
1043
1044         /* Draw scroll */
1045         mywinset(curarea->win); // reset scissor too
1046         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
1047       myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1048       if(G.v2d->scroll) drawscroll(0);
1049         }
1050
1051         if(G.v2d->mask.xmin!=0) {
1052                 /* Draw channel names */
1053                 draw_channel_names();
1054
1055                 if(sa->winx > 50 + NAMEWIDTH + SLIDERWIDTH) {
1056                         if (act) {
1057                                 /* if there is an action, draw sliders for its
1058                                  * ipo-curve channels in the action window
1059                                  */
1060                                 action_icu_buts(G.saction);
1061                         }
1062                         else if (key) {
1063                                 /* if there is a mesh with rvk's selected,
1064                                  * then draw the key frames in the action window
1065                                  */
1066                                 meshactionbuts(G.saction, OBACT, key);
1067                         }
1068                 }
1069         }
1070         
1071         mywinset(curarea->win); // reset scissor too
1072         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1073         draw_area_emboss(sa);
1074
1075         /* it is important to end a view in a transform compatible with buttons */
1076         bwin_scalematrix(sa->win, G.saction->blockscale, G.saction->blockscale, G.saction->blockscale);
1077         action_blockhandlers(sa);
1078
1079         curarea->win_swap= WIN_BACK_OK;
1080 }
1081
1082 /* *************************** Keyframe Drawing *************************** */
1083
1084 static void add_bezt_to_keycolumnslist(ListBase *keys, BezTriple *bezt)
1085 {
1086         /* The equivilant of add_to_cfra_elem except this version 
1087          * makes ActKeyColumns - one of the two datatypes required
1088          * for action editor drawing.
1089          */
1090         ActKeyColumn *ak, *akn;
1091         
1092         if (!(keys) || !(bezt)) return;
1093         
1094         /* try to find a keyblock that starts on the previous beztriple */
1095         for (ak= keys->first; ak; ak= ak->next) {
1096                 /* do because of double keys */
1097                 if (ak->cfra == bezt->vec[1][0]) {                      
1098                         /* set selection status and 'touched' status */
1099                         if (BEZSELECTED(bezt)) ak->sel = SELECT;
1100                         ak->modified += 1;
1101                         
1102                         return;
1103                 }
1104                 else if (ak->cfra > bezt->vec[1][0]) break;
1105         }
1106         
1107         /* add new block */
1108         akn= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
1109         if (ak) BLI_insertlinkbefore(keys, ak, akn);
1110         else BLI_addtail(keys, akn);
1111         
1112         akn->cfra= bezt->vec[1][0];
1113         akn->modified += 1;
1114         
1115         // TODO: handle type = bezt->h1 or bezt->h2
1116         akn->handle_type= 0; 
1117         
1118         if (BEZSELECTED(bezt))
1119                 akn->sel = SELECT;
1120         else
1121                 akn->sel = 0;
1122 }
1123
1124 static void add_bezt_to_keyblockslist(ListBase *blocks, IpoCurve *icu, int index)
1125 {
1126         /* The equivilant of add_to_cfra_elem except this version 
1127          * makes ActKeyBlocks - one of the two datatypes required
1128          * for action editor drawing.
1129          */
1130         ActKeyBlock *ab, *abn;
1131         BezTriple *beztn=NULL, *prev=NULL;
1132         BezTriple *bezt;
1133         int v;
1134         
1135         /* get beztriples */
1136         beztn= (icu->bezt + index);
1137         
1138         for (v=0, bezt=icu->bezt; v<icu->totvert; v++, bezt++) {
1139                 /* skip if beztriple is current */
1140                 if (v != index) {
1141                         /* check if beztriple is immediately before */
1142                         if (beztn->vec[1][0] > bezt->vec[1][0]) {
1143                                 /* check if closer than previous was */
1144                                 if (prev) {
1145                                         if (prev->vec[1][0] < bezt->vec[1][0])
1146                                                 prev= bezt;
1147                                 }
1148                                 else {
1149                                         prev= bezt;
1150                                 }
1151                         }
1152                 }
1153         }
1154         
1155         /* check if block needed - same value? */
1156         if ((!prev) || (!beztn))
1157                 return;
1158         if (beztn->vec[1][1] != prev->vec[1][1])
1159                 return;
1160         
1161         /* try to find a keyblock that starts on the previous beztriple */
1162         for (ab= blocks->first; ab; ab= ab->next) {
1163                 /* check if alter existing block or add new block */
1164                 if (ab->start == prev->vec[1][0]) {                     
1165                         /* set selection status and 'touched' status */
1166                         if (BEZSELECTED(beztn)) ab->sel = SELECT;
1167                         ab->modified += 1;
1168                         
1169                         return;
1170                 }
1171                 else if (ab->start > prev->vec[1][0]) break;
1172         }
1173         
1174         /* add new block */
1175         abn= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
1176         if (ab) BLI_insertlinkbefore(blocks, ab, abn);
1177         else BLI_addtail(blocks, abn);
1178         
1179         abn->start= prev->vec[1][0];
1180         abn->end= beztn->vec[1][0];
1181         abn->val= beztn->vec[1][1];
1182         
1183         if (BEZSELECTED(prev) || BEZSELECTED(beztn))
1184                 abn->sel = SELECT;
1185         abn->modified = 1;
1186 }
1187
1188 /* helper function - find actkeycolumn that occurs on cframe */
1189 static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe)
1190 {
1191         ActKeyColumn *ak;
1192         
1193         if (keys==NULL) 
1194                 return NULL;
1195          
1196         for (ak= keys->first; ak; ak= ak->next) {
1197                 if (ak->cfra == cframe)
1198                         return ak;
1199         }
1200         
1201         return NULL;
1202 }
1203
1204 static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos)
1205 {
1206         ActKeyColumn *ak;
1207         ActKeyBlock *ab;
1208         
1209         glEnable(GL_BLEND);
1210         
1211         /* draw keyblocks */
1212         if (blocks) {
1213                 for (ab= blocks->first; ab; ab= ab->next) {
1214                         short startCurves, endCurves, totCurves;
1215                         
1216                         /* find out how many curves occur at each keyframe */
1217                         ak= cfra_find_actkeycolumn(keys, ab->start);
1218                         startCurves = (ak)? ak->totcurve: 0;
1219                         
1220                         ak= cfra_find_actkeycolumn(keys, ab->end);
1221                         endCurves = (ak)? ak->totcurve: 0;
1222                         
1223                         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
1224                         if (!startCurves && !endCurves) 
1225                                 continue;
1226                         else
1227                                 totCurves = (startCurves>endCurves)? endCurves: startCurves;
1228                                 
1229                         if (ab->totcurve >= totCurves) {
1230                                 int sc_xa, sc_ya;
1231                                 int sc_xb, sc_yb;
1232                                 
1233                                 /* get co-ordinates of block */
1234                                 gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya);
1235                                 gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb);
1236                                 
1237                                 /* draw block */
1238                                 if (ab->sel & 1)
1239                                         BIF_ThemeColor4(TH_STRIP_SELECT);
1240                                 else
1241                                         BIF_ThemeColor4(TH_STRIP);
1242                                 glRectf(sc_xa,  sc_ya-3,  sc_xb,  sc_yb+5);
1243                         }
1244                 }
1245         }
1246         
1247         /* draw keys */
1248         if (keys) {
1249                 for (ak= keys->first; ak; ak= ak->next) {
1250                         int sc_x, sc_y;
1251                         
1252                         /* get co-ordinate to draw at */
1253                         gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
1254                         
1255                         if(ak->sel & 1) BIF_icon_draw_aspect(sc_x-7, sc_y-6, ICON_SPACE2, 1.0f);
1256                         else BIF_icon_draw_aspect(sc_x-7, sc_y-6, ICON_SPACE3, 1.0f);
1257                 }       
1258         }
1259         
1260         glDisable(GL_BLEND);
1261 }
1262
1263 void draw_object_channel(gla2DDrawInfo *di, Object *ob, float ypos)
1264 {
1265         ListBase keys = {0, 0};
1266         ListBase blocks = {0, 0};
1267
1268         ob_to_keylist(ob, &keys, &blocks);
1269         draw_keylist(di, &keys, &blocks, ypos);
1270         
1271         BLI_freelistN(&keys);
1272         BLI_freelistN(&blocks);
1273 }
1274
1275 void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, float ypos)
1276 {
1277         ListBase keys = {0, 0};
1278         ListBase blocks = {0, 0};
1279
1280         ipo_to_keylist(ipo, &keys, &blocks);
1281         draw_keylist(di, &keys, &blocks, ypos);
1282         
1283         BLI_freelistN(&keys);
1284         BLI_freelistN(&blocks);
1285 }
1286
1287 void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, float ypos)
1288 {
1289         ListBase keys = {0, 0};
1290         ListBase blocks = {0, 0};
1291
1292         icu_to_keylist(icu, &keys, &blocks);
1293         draw_keylist(di, &keys, &blocks, ypos);
1294         
1295         BLI_freelistN(&keys);
1296         BLI_freelistN(&blocks);
1297 }
1298
1299 void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos)
1300 {
1301         ListBase keys = {0, 0};
1302
1303         action_to_keylist(act, &keys, NULL);
1304         draw_keylist(di, &keys, NULL, ypos);
1305         BLI_freelistN(&keys);
1306 }
1307
1308 void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks)
1309 {
1310         bConstraintChannel *conchan;
1311
1312         if (ob) {
1313                 /* Add object keyframes */
1314                 if (ob->ipo)
1315                         ipo_to_keylist(ob->ipo, keys, blocks);
1316                 
1317                 /* Add constraint keyframes */
1318                 for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
1319                         if(conchan->ipo)
1320                                 ipo_to_keylist(conchan->ipo, keys, blocks);             
1321                 }
1322                         
1323                 /* Add object data keyframes */
1324                 //              TODO??
1325         }
1326 }
1327
1328 void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks)
1329 {
1330         BezTriple *bezt;
1331         ActKeyColumn *ak;
1332         ActKeyBlock *ab;
1333         int v;
1334         
1335         if (icu && icu->totvert) {
1336                 /* loop through beztriples, making ActKeys and ActKeyBlocks */
1337                 bezt= icu->bezt;
1338                 
1339                 for (v=0; v<icu->totvert; v++, bezt++) {
1340                         add_bezt_to_keycolumnslist(keys, bezt);
1341                         if (blocks) add_bezt_to_keyblockslist(blocks, icu, v);
1342                 }
1343                 
1344                 /* update the number of curves that elements have appeared in  */
1345                 if (keys) {
1346                         for (ak= keys->first; ak; ak= ak->next) {
1347                                 if (ak->modified) {
1348                                         ak->modified = 0;
1349                                         ak->totcurve += 1;
1350                                 }
1351                         }
1352                 }
1353                 if (blocks) {
1354                         for (ab= blocks->first; ab; ab= ab->next) {
1355                                 if (ab->modified) {
1356                                         ab->modified = 0;
1357                                         ab->totcurve += 1;
1358                                 }
1359                         }
1360                 }
1361         }
1362 }
1363
1364 void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks)
1365 {
1366         IpoCurve *icu;
1367         
1368         if (ipo) {
1369                 for (icu= ipo->curve.first; icu; icu= icu->next)
1370                         icu_to_keylist(icu, keys, blocks);
1371         }
1372 }
1373
1374 void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks)
1375 {
1376         bActionChannel *achan;
1377         bConstraintChannel *conchan;
1378
1379         if (act) {
1380                 /* loop through action channels */
1381                 for (achan= act->chanbase.first; achan; achan= achan->next) {
1382                         /* firstly, add keys from action channel's ipo block */
1383                         if (achan->ipo)
1384                                 ipo_to_keylist(achan->ipo, keys, blocks);
1385                         
1386                         /* then, add keys from constraint channels */
1387                         for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
1388                                 if (conchan->ipo)
1389                                         ipo_to_keylist(achan->ipo, keys, blocks);
1390                         }
1391                 }
1392         }
1393 }
1394