== Action/IPO Editors - Code Cleanup ==
[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): Joshua Leung
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 'eye' indicating whether channel's ipo is muted */
408                         if (achan->ipo) {
409                                 if (achan->ipo->muteipo) 
410                                         BIF_icon_draw(NAMEWIDTH-32, y-CHANNELHEIGHT/2, ICON_RESTRICT_VIEW_ON);
411                                 else 
412                                         BIF_icon_draw(NAMEWIDTH-32, y-CHANNELHEIGHT/2, ICON_RESTRICT_VIEW_OFF);
413                         }
414                         
415                         /* draw 'lock' indicating whether channel is protected */
416                         if (EDITABLE_ACHAN(achan)==0) 
417                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
418                         else 
419                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);
420                         y-=CHANNELHEIGHT+CHANNELSKIP;
421                         
422                         if (EXPANDED_ACHAN(achan)) {
423                                 /* Draw IPO-curves show/hide widget */
424                                 if (achan->ipo) {                                       
425                                         /* draw backing strip behind */
426                                         BIF_ThemeColorShade(TH_HEADER, -20);
427                                         glRectf(x+7,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
428                                         
429                                         /* draw expand/collapse triangle for showing sub-channels  */
430                                         if (FILTER_IPO_ACHAN(achan))
431                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_DOWN);
432                                         else
433                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_RIGHT);
434                                         
435                                         /* draw icon showing type of ipo-block */
436                                         BIF_icon_draw(x+24, y-CHANNELHEIGHT/2, geticon_ipo_blocktype(achan->ipo->blocktype));
437                                         
438                                         /* draw name of ipo-block */
439                                         if (SEL_ACHAN(achan))
440                                                 BIF_ThemeColor(TH_TEXT_HI);
441                                         else
442                                                 BIF_ThemeColor(TH_TEXT);
443                                         glRasterPos2f(x+40,  y-4);
444                                         BMF_DrawString(G.font, "IPO Curves"); // TODO: make proper naming scheme
445                                 
446                                         y-=CHANNELHEIGHT+CHANNELSKIP;
447                                 
448                                         /* Draw IPO-curve-channels? */
449                                         if (FILTER_IPO_ACHAN(achan)) {
450                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
451                                                         char *icu_name= getname_ipocurve(icu);
452                                                         
453                                                         /* draw backing strip behind ipo-curve channel*/
454                                                         BIF_ThemeColorShade(TH_HEADER, -40);
455                                                         glRectf(x+14,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
456                                                         
457                                                         /* draw name of ipo-curve channel */
458                                                         if (SEL_ICU(icu))
459                                                                 BIF_ThemeColor(TH_TEXT_HI);
460                                                         else
461                                                                 BIF_ThemeColor(TH_TEXT);
462                                                         glRasterPos2f(x+24,  y-4);
463                                                         BMF_DrawString(G.font, icu_name);
464                                                         
465                                                         /* draw 'eye' indicating whether channel's ipo curve is muted */
466                                                         if (icu->flag & IPO_MUTE) 
467                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_RESTRICT_VIEW_ON);
468                                                         else 
469                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_RESTRICT_VIEW_OFF);
470                                                         
471 #if 0 /* tempolarily disabled until all ipo-code can support this option */
472                                                         /* draw 'lock' to indicate if ipo-curve channel is protected */
473                                                         if (EDITABLE_ICU(icu)==0) 
474                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
475                                                         else 
476                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);  
477 #endif
478                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
479                                                 }
480                                         }
481                                 }
482
483                                 /* Draw constraints show/hide widget */
484                                 if (achan->constraintChannels.first) {
485                                         /* draw backing strip behind */
486                                         BIF_ThemeColorShade(TH_HEADER, -20);
487                                         glRectf(x+7,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
488                                         
489                                         /* draw expand/collapse triangle for showing sub-channels  */
490                                         if (FILTER_CON_ACHAN(achan))
491                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_DOWN);
492                                         else
493                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_RIGHT);
494                                         
495                                         /* draw constraint icon */
496                                         BIF_icon_draw(x+24, y-CHANNELHEIGHT/2, ICON_CONSTRAINT);
497                                         
498                                         /* draw name of widget */
499                                         if (SEL_ACHAN(achan))
500                                                 BIF_ThemeColor(TH_TEXT_HI);
501                                         else
502                                                 BIF_ThemeColor(TH_TEXT);
503                                         glRasterPos2f(x+40,  y-4);
504                                         BMF_DrawString(G.font, "Constraints");
505                                 
506                                         y-=CHANNELHEIGHT+CHANNELSKIP;
507                                 
508                                         /* Draw constraint channels?  */
509                                         if (FILTER_CON_ACHAN(achan)) {
510                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
511                                                         /* draw backing strip behind constraint channel*/
512                                                         BIF_ThemeColorShade(TH_HEADER, -40);
513                                                         glRectf(x+14,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
514                                                         
515                                                         /* draw name of constraint channel */
516                                                         if (SEL_CONCHAN(conchan))
517                                                                 BIF_ThemeColor(TH_TEXT_HI);
518                                                         else
519                                                                 BIF_ThemeColor(TH_TEXT);
520                                                         glRasterPos2f(x+25,  y-4);
521                                                         BMF_DrawString(G.font, conchan->name);
522                                                         
523                                                         /* draw 'eye' indicating whether channel's ipo is muted */
524                                                         if (conchan->ipo) {
525                                                                 if (conchan->ipo->muteipo) 
526                                                                         BIF_icon_draw(NAMEWIDTH-32, y-CHANNELHEIGHT/2, ICON_RESTRICT_VIEW_ON);
527                                                                 else 
528                                                                         BIF_icon_draw(NAMEWIDTH-32, y-CHANNELHEIGHT/2, ICON_RESTRICT_VIEW_OFF);
529                                                         }
530                                                         
531                                                         /* draw 'lock' to indicate if constraint channel is protected */
532                                                         if (EDITABLE_CONCHAN(conchan)==0) 
533                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
534                                                         else 
535                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);  
536                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
537                                                 }
538                                         }
539                                 }
540                         }
541                         
542                         glDisable(GL_BLEND);
543                 }
544         }
545 }
546
547
548 static void draw_action_mesh_names(Key *key) 
549 {
550         /* draws the names of the rvk keys in the
551          * left side of the action window
552          */
553         int          i;
554         char     keyname[32];
555         float    x, y;
556         KeyBlock *kb;
557
558         x = 0.0;
559         y= 0.0;
560
561         kb= key->block.first;
562
563         for (i=1 ; i < key->totkey ; ++ i) {
564                 glColor3ub(0xAA, 0xAA, 0xAA);
565                 glRectf(x,      y-CHANNELHEIGHT/2,      (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
566
567                 glColor3ub(0, 0, 0);
568
569                 glRasterPos2f(x+8,      y-4);
570                 kb = kb->next;
571                 /* Blender now has support for named
572                  * key blocks. If a name hasn't
573                  * been set for an key block then
574                  * just display the key number -- 
575                  * otherwise display the name stored
576                  * in the keyblock.
577                  */
578                 if (kb->name[0] == '\0') {
579                   sprintf(keyname, "Key %d", i);
580                   BMF_DrawString(G.font, keyname);
581                 }
582                 else {
583                   BMF_DrawString(G.font, kb->name);
584                 }
585
586                 y-=CHANNELHEIGHT+CHANNELSKIP;
587
588         }
589 }
590
591 /* left hand part */
592 static void draw_channel_names(void) 
593 {
594         short ofsx, ofsy = 0; 
595         bAction *act;
596         Key *key;
597
598         /* Clip to the scrollable area */
599         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
600                 if(G.v2d->scroll) {     
601                         ofsx= curarea->winrct.xmin;     
602                         ofsy= curarea->winrct.ymin;
603                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
604                                            (ofsy+G.v2d->mask.ymax) -
605                                            (ofsy+G.v2d->mask.ymin)); 
606                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
607                                           (ofsy+G.v2d->mask.ymax) -
608                                           (ofsy+G.v2d->mask.ymin));
609                 }
610         }
611         
612         myortho2(0,     NAMEWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);   //      Scaling
613         
614         glColor3ub(0x00, 0x00, 0x00);
615
616         act=G.saction->action;
617
618         if (act) {
619                 /* if there is a selected action then
620                  * draw the channel names
621                  */
622                 draw_action_channel_names(act);
623         }
624         else if ( (key = get_action_mesh_key()) ) {
625                 /* if there is a mesh selected with rvk's,
626                  * then draw the RVK names
627                  */
628                 draw_action_mesh_names(key);
629     }
630
631     myortho2(0, NAMEWIDTH, 0, (ofsy+G.v2d->mask.ymax) -
632               (ofsy+G.v2d->mask.ymin)); //      Scaling
633
634 }
635
636 int count_action_levels(bAction *act)
637 {
638         bActionChannel *achan;
639         int y=0;
640
641         if (!act) 
642                 return 0;
643
644         for (achan=act->chanbase.first; achan; achan=achan->next) {
645                 if(VISIBLE_ACHAN(achan)) {
646                         y++;
647                         
648                         if (EXPANDED_ACHAN(achan)) {
649                                 if (achan->constraintChannels.first) {
650                                         y++;
651                                         if (FILTER_CON_ACHAN(achan))
652                                                 y += BLI_countlist(&achan->constraintChannels);
653                                 }
654                                 else if (achan->ipo) {
655                                         y++;
656                                         if (FILTER_IPO_ACHAN(achan))
657                                                 y += BLI_countlist(&achan->ipo->curve);
658                                 }
659                         }
660                 }
661         }
662
663         return y;
664 }
665
666 /* sets or clears hidden flags */
667 void check_action_context(SpaceAction *saction)
668 {
669         bActionChannel *achan;
670         
671         if(saction->action==NULL) return;
672         
673         for (achan=saction->action->chanbase.first; achan; achan=achan->next)
674                 achan->flag &= ~ACHAN_HIDDEN;
675         
676         if (G.saction->pin==0 && OBACT) {
677                 Object *ob= OBACT;
678                 bPoseChannel *pchan;
679                 bArmature *arm= ob->data;
680                 
681                 for (achan=saction->action->chanbase.first; achan; achan=achan->next) {
682                         pchan= get_pose_channel(ob->pose, achan->name);
683                         if (pchan) {
684                                 if ((pchan->bone->layer & arm->layer)==0)
685                                         achan->flag |= ACHAN_HIDDEN;
686                                 else if (pchan->bone->flag & BONE_HIDDEN_P)
687                                         achan->flag |= ACHAN_HIDDEN;
688                         }
689                 }
690         }
691 }
692
693 static void draw_channel_strips(SpaceAction *saction)
694 {
695         rcti scr_rct;
696         gla2DDrawInfo *di;
697         bAction *act;
698         bActionChannel *achan;
699         bConstraintChannel *conchan;
700         IpoCurve *icu;
701         float y, sta, end;
702         int act_start, act_end, dummy;
703         char col1[3], col2[3];
704         
705         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
706         BIF_GetThemeColor3ubv(TH_HILITE, col1);
707
708         act= saction->action;
709         if (!act)
710                 return;
711
712         scr_rct.xmin= saction->area->winrct.xmin + saction->v2d.mask.xmin;
713         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
714         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
715         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
716         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
717
718         /* if in NLA there's a strip active, map the view */
719         if (NLA_ACTION_SCALED)
720                 map_active_strip(di, OBACT, 0);
721         
722         /* start and end of action itself */
723         calc_action_range(act, &sta, &end, 0);
724         gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
725         gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
726         
727         if (NLA_ACTION_SCALED)
728                 map_active_strip(di, OBACT, 1);
729         
730         /* first backdrop strips */
731         y = 0.0;
732         glEnable(GL_BLEND);
733         for (achan=act->chanbase.first; achan; achan= achan->next) {
734                 if(VISIBLE_ACHAN(achan)) {
735                         int frame1_x, channel_y;
736                         
737                         gla2DDrawTranslatePt(di, G.v2d->cur.xmin, y, &frame1_x, &channel_y);
738                         
739                         if (SEL_ACHAN(achan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
740                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
741                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
742                         
743                         if (SEL_ACHAN(achan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
744                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
745                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2,  act_end,  channel_y+CHANNELHEIGHT/2);
746                         
747                         /*      Increment the step */
748                         y-=CHANNELHEIGHT+CHANNELSKIP;
749                         
750                         /* Draw sub channels */
751                         if (EXPANDED_ACHAN(achan)) {
752                                 /* Draw ipo channels */
753                                 if (achan->ipo) {
754                                         y-=CHANNELHEIGHT+CHANNELSKIP;
755                                         
756                                         if (FILTER_IPO_ACHAN(achan)) {
757                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
758                                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
759                                                         
760                                                         if (SEL_ICU(icu)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
761                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
762                                                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
763                                                         
764                                                         if (SEL_ICU(icu)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
765                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
766                                                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2+4,  act_end,  channel_y+CHANNELHEIGHT/2-4);
767                                                         
768                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
769                                                 }
770                                         }
771                                 }
772                                 
773                                 /* Draw constraint channels */
774                                 if (achan->constraintChannels.first) {
775                                         y-=CHANNELHEIGHT+CHANNELSKIP;
776                                         
777                                         if (FILTER_CON_ACHAN(achan)) {
778                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
779                                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
780                                                         
781                                                         if (SEL_CONCHAN(conchan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
782                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
783                                                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
784                                                         
785                                                         if (SEL_CONCHAN(conchan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
786                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
787                                                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2+4,  act_end,  channel_y+CHANNELHEIGHT/2-4);
788                                                         
789                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
790                                                 }
791                                         }
792                                 }
793                         }
794                 }
795         }               
796         glDisable(GL_BLEND);
797         
798         if (NLA_ACTION_SCALED)
799                 map_active_strip(di, OBACT, 0);
800         
801         /* keyframes  */
802         y = 0.0;
803         for (achan= act->chanbase.first; achan; achan= achan->next) {
804                 if(VISIBLE_ACHAN(achan)) {
805                         
806                         draw_ipo_channel(di, achan->ipo, y);
807                         y-=CHANNELHEIGHT+CHANNELSKIP;
808
809                         /* Draw sub channels */
810                         if (EXPANDED_ACHAN(achan)) {
811                                 /* Draw ipo curves */
812                                 if (achan->ipo) {
813                                         y-=CHANNELHEIGHT+CHANNELSKIP;
814                                         
815                                         if (FILTER_IPO_ACHAN(achan)) {
816                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
817                                                         draw_icu_channel(di, icu, y);
818                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
819                                                 }
820                                         }
821                                 }
822                                 
823                                 /* Draw constraint channels */
824                                 if (achan->constraintChannels.first) {
825                                         y-=CHANNELHEIGHT+CHANNELSKIP;
826                                         
827                                         if (FILTER_CON_ACHAN(achan)) {
828                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
829                                                         draw_ipo_channel(di, conchan->ipo, y);
830                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
831                                                 }
832                                         }
833                                 }
834                         }
835                 }
836         }
837
838         if(saction->flag & SACTION_MOVING) {
839                 int frame1_x, channel_y;
840                 gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &channel_y);
841                 cpack(0x0);
842                 glBegin(GL_LINES);
843                 glVertex2f(frame1_x, G.v2d->mask.ymin - 100);
844                 glVertex2f(frame1_x, G.v2d->mask.ymax);
845                 glEnd();
846         }
847         
848         glaEnd2DDraw(di);
849 }
850
851 static void draw_mesh_strips(SpaceAction *saction, Key *key)
852 {
853         /* draw the RVK keyframes */
854         rcti scr_rct;
855         gla2DDrawInfo *di;
856         float   y, ybase;
857         IpoCurve *icu;
858         char col1[3], col2[3];
859         
860         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
861         BIF_GetThemeColor3ubv(TH_HILITE, col1);
862
863         if (!key->ipo) return;
864
865         scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
866         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
867         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
868         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
869         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
870
871         ybase = 0;
872
873         for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
874                 int frame1_x, channel_y;
875                 
876                 /* lets not deal with the "speed" Ipo */
877                 if (icu->adrcode==0) continue;
878                 
879                 y = ybase       - (CHANNELHEIGHT+CHANNELSKIP)*(icu->adrcode-1);
880                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
881                         
882                 /* all frames that have a frame number less than one
883                  * get a desaturated orange background
884                  */
885                 glEnable(GL_BLEND);
886                 glColor4ub(col2[0], col2[1], col2[2], 0x22);
887                 glRectf(0,        channel_y-CHANNELHEIGHT/2,  
888                                 frame1_x, channel_y+CHANNELHEIGHT/2);
889
890                 /* frames one and higher get a saturated orange background */
891                 glColor4ub(col2[0], col2[1], col2[2], 0x44);
892                 glRectf(frame1_x,         channel_y-CHANNELHEIGHT/2,  
893                                 G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
894                 glDisable(GL_BLEND);
895
896                 /* draw the keyframes */
897                 draw_icu_channel(di, icu, y); 
898         }
899
900         glaEnd2DDraw(di);
901 }
902
903 /* ********* action panel *********** */
904
905
906 void do_actionbuts(unsigned short event)
907 {
908         switch(event) {
909         case REDRAWVIEW3D:
910                 allqueue(REDRAWVIEW3D, 0);
911                 break;
912         case B_REDR:
913                 allqueue(REDRAWACTION, 0);
914                 break;
915         }
916 }
917
918
919 static void action_panel_properties(short cntrl)        // ACTION_HANDLER_PROPERTIES
920 {
921         uiBlock *block;
922
923         block= uiNewBlock(&curarea->uiblocks, "action_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
924         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
925         uiSetPanelHandler(ACTION_HANDLER_PROPERTIES);  // for close and esc
926         if(uiNewPanel(curarea, block, "Transform Properties", "Action", 10, 230, 318, 204)==0) return;
927
928         uiDefBut(block, LABEL, 0, "test text",          10,180,300,19, 0, 0, 0, 0, 0, "");
929
930 }
931
932 static void action_blockhandlers(ScrArea *sa)
933 {
934         SpaceAction *sact= sa->spacedata.first;
935         short a;
936         
937         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
938                 switch(sact->blockhandler[a]) {
939
940                 case ACTION_HANDLER_PROPERTIES:
941                         action_panel_properties(sact->blockhandler[a+1]);
942                         break;
943                 
944                 }
945                 /* clear action value for event */
946                 sact->blockhandler[a+1]= 0;
947         }
948         uiDrawBlocksPanels(sa, 0);
949 }
950
951 /* ************************* Action Editor Space ***************************** */
952
953 void drawactionspace(ScrArea *sa, void *spacedata)
954 {
955         short ofsx = 0, ofsy = 0;
956         bAction *act;
957         Key *key;
958         float col[3];
959         short maxymin;
960
961         if (!G.saction)
962                 return;
963
964         /* warning; blocks need to be freed each time, handlers dont remove  */
965         uiFreeBlocksWin(&sa->uiblocks, sa->win);
966
967         if (!G.saction->pin) {
968                 /* allow more than one active action sometime? */
969                 if (OBACT)
970                         G.saction->action = OBACT->action;
971                 else
972                         G.saction->action=NULL;
973         }
974         key = get_action_mesh_key();
975         act= G.saction->action;
976
977         /* Damn I hate hunting to find my rvk's because
978          * they have scrolled off of the screen ... this
979          * oughta fix it
980          */
981         
982         if (!act && key) {
983                 if (G.v2d->cur.ymin < -CHANNELHEIGHT) 
984                         G.v2d->cur.ymin = -CHANNELHEIGHT;
985                 
986                 maxymin = -(key->totkey*(CHANNELHEIGHT+CHANNELSKIP));
987                 if (G.v2d->cur.ymin > maxymin) G.v2d->cur.ymin = maxymin;
988         }
989
990         /* Lets make sure the width of the left hand of the screen
991          * is set to an appropriate value based on whether sliders
992          * are showing of not
993          */
994         if (((key)||(act)) && (G.saction->flag & SACTION_SLIDERS)) 
995                 ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
996         else 
997                 ACTWIDTH = NAMEWIDTH;
998
999         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
1000
1001         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
1002
1003         /* background color for entire window (used in lefthand part tho) */
1004         BIF_GetThemeColor3fv(TH_HEADER, col);
1005         glClearColor(col[0], col[1], col[2], 0.0); 
1006         glClear(GL_COLOR_BUFFER_BIT);
1007         
1008         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
1009                 if(G.v2d->scroll) {     
1010                         ofsx= curarea->winrct.xmin;     
1011                         ofsy= curarea->winrct.ymin;
1012                         glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
1013                                            ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1014                                            ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
1015                         glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
1016                                           ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1017                                           ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
1018                 }
1019         }
1020
1021         BIF_GetThemeColor3fv(TH_BACK, col);
1022         glClearColor(col[0], col[1], col[2], 0.0);
1023         glClear(GL_COLOR_BUFFER_BIT);
1024
1025         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
1026         bwin_clear_viewmat(sa->win);    /* clear buttons view */
1027         glLoadIdentity();
1028
1029         /*      Draw backdrop */
1030         calc_ipogrid(); 
1031         draw_ipogrid();
1032
1033         check_action_context(G.saction);
1034         
1035         /* Draw channel strips */
1036         if (act) {
1037                 draw_channel_strips(G.saction);
1038         }
1039         else if (key) {
1040                 /* if there is a mesh with rvk's selected,
1041                  * then draw the key frames in the action window
1042                  */
1043                 draw_mesh_strips(G.saction, key);
1044         }
1045         
1046         /* reset matrices for stuff to be drawn on top of keys*/
1047         glViewport(ofsx+G.v2d->mask.xmin,  
1048              ofsy+G.v2d->mask.ymin, 
1049              ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1050              ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
1051         glScissor(ofsx+G.v2d->mask.xmin,  
1052             ofsy+G.v2d->mask.ymin, 
1053             ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1054             ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
1055         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax,  G.v2d->cur.ymin, G.v2d->cur.ymax);
1056         
1057         /* Draw current frame */
1058         draw_cfra_action();
1059         
1060         /* Draw markers */
1061         draw_markers_timespace();
1062         
1063         /* Draw 'curtains' for preview */
1064         draw_anim_preview_timespace();
1065
1066         /* Draw scroll */
1067         mywinset(curarea->win); // reset scissor too
1068         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
1069       myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1070       if(G.v2d->scroll) drawscroll(0);
1071         }
1072
1073         if(G.v2d->mask.xmin!=0) {
1074                 /* Draw channel names */
1075                 draw_channel_names();
1076
1077                 if(sa->winx > 50 + NAMEWIDTH + SLIDERWIDTH) {
1078                         if (act) {
1079                                 /* if there is an action, draw sliders for its
1080                                  * ipo-curve channels in the action window
1081                                  */
1082                                 action_icu_buts(G.saction);
1083                         }
1084                         else if (key) {
1085                                 /* if there is a mesh with rvk's selected,
1086                                  * then draw the key frames in the action window
1087                                  */
1088                                 meshactionbuts(G.saction, OBACT, key);
1089                         }
1090                 }
1091         }
1092         
1093         mywinset(curarea->win); // reset scissor too
1094         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1095         draw_area_emboss(sa);
1096
1097         /* it is important to end a view in a transform compatible with buttons */
1098         bwin_scalematrix(sa->win, G.saction->blockscale, G.saction->blockscale, G.saction->blockscale);
1099         action_blockhandlers(sa);
1100
1101         curarea->win_swap= WIN_BACK_OK;
1102 }
1103
1104 /* *************************** Keyframe Drawing *************************** */
1105
1106 static void add_bezt_to_keycolumnslist(ListBase *keys, BezTriple *bezt)
1107 {
1108         /* The equivilant of add_to_cfra_elem except this version 
1109          * makes ActKeyColumns - one of the two datatypes required
1110          * for action editor drawing.
1111          */
1112         ActKeyColumn *ak, *akn;
1113         
1114         if (!(keys) || !(bezt)) return;
1115         
1116         /* try to find a keyblock that starts on the previous beztriple */
1117         for (ak= keys->first; ak; ak= ak->next) {
1118                 /* do because of double keys */
1119                 if (ak->cfra == bezt->vec[1][0]) {                      
1120                         /* set selection status and 'touched' status */
1121                         if (BEZSELECTED(bezt)) ak->sel = SELECT;
1122                         ak->modified += 1;
1123                         
1124                         return;
1125                 }
1126                 else if (ak->cfra > bezt->vec[1][0]) break;
1127         }
1128         
1129         /* add new block */
1130         akn= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
1131         if (ak) BLI_insertlinkbefore(keys, ak, akn);
1132         else BLI_addtail(keys, akn);
1133         
1134         akn->cfra= bezt->vec[1][0];
1135         akn->modified += 1;
1136         
1137         // TODO: handle type = bezt->h1 or bezt->h2
1138         akn->handle_type= 0; 
1139         
1140         if (BEZSELECTED(bezt))
1141                 akn->sel = SELECT;
1142         else
1143                 akn->sel = 0;
1144 }
1145
1146 static void add_bezt_to_keyblockslist(ListBase *blocks, IpoCurve *icu, int index)
1147 {
1148         /* The equivilant of add_to_cfra_elem except this version 
1149          * makes ActKeyBlocks - one of the two datatypes required
1150          * for action editor drawing.
1151          */
1152         ActKeyBlock *ab, *abn;
1153         BezTriple *beztn=NULL, *prev=NULL;
1154         BezTriple *bezt;
1155         int v;
1156         
1157         /* get beztriples */
1158         beztn= (icu->bezt + index);
1159         
1160         for (v=0, bezt=icu->bezt; v<icu->totvert; v++, bezt++) {
1161                 /* skip if beztriple is current */
1162                 if (v != index) {
1163                         /* check if beztriple is immediately before */
1164                         if (beztn->vec[1][0] > bezt->vec[1][0]) {
1165                                 /* check if closer than previous was */
1166                                 if (prev) {
1167                                         if (prev->vec[1][0] < bezt->vec[1][0])
1168                                                 prev= bezt;
1169                                 }
1170                                 else {
1171                                         prev= bezt;
1172                                 }
1173                         }
1174                 }
1175         }
1176         
1177         /* check if block needed - same value? */
1178         if ((!prev) || (!beztn))
1179                 return;
1180         if (beztn->vec[1][1] != prev->vec[1][1])
1181                 return;
1182         
1183         /* try to find a keyblock that starts on the previous beztriple */
1184         for (ab= blocks->first; ab; ab= ab->next) {
1185                 /* check if alter existing block or add new block */
1186                 if (ab->start == prev->vec[1][0]) {                     
1187                         /* set selection status and 'touched' status */
1188                         if (BEZSELECTED(beztn)) ab->sel = SELECT;
1189                         ab->modified += 1;
1190                         
1191                         return;
1192                 }
1193                 else if (ab->start > prev->vec[1][0]) break;
1194         }
1195         
1196         /* add new block */
1197         abn= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
1198         if (ab) BLI_insertlinkbefore(blocks, ab, abn);
1199         else BLI_addtail(blocks, abn);
1200         
1201         abn->start= prev->vec[1][0];
1202         abn->end= beztn->vec[1][0];
1203         abn->val= beztn->vec[1][1];
1204         
1205         if (BEZSELECTED(prev) || BEZSELECTED(beztn))
1206                 abn->sel = SELECT;
1207         abn->modified = 1;
1208 }
1209
1210 /* helper function - find actkeycolumn that occurs on cframe */
1211 static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe)
1212 {
1213         ActKeyColumn *ak;
1214         
1215         if (keys==NULL) 
1216                 return NULL;
1217          
1218         for (ak= keys->first; ak; ak= ak->next) {
1219                 if (ak->cfra == cframe)
1220                         return ak;
1221         }
1222         
1223         return NULL;
1224 }
1225
1226 static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos)
1227 {
1228         ActKeyColumn *ak;
1229         ActKeyBlock *ab;
1230         
1231         glEnable(GL_BLEND);
1232         
1233         /* draw keyblocks */
1234         if (blocks) {
1235                 for (ab= blocks->first; ab; ab= ab->next) {
1236                         short startCurves, endCurves, totCurves;
1237                         
1238                         /* find out how many curves occur at each keyframe */
1239                         ak= cfra_find_actkeycolumn(keys, ab->start);
1240                         startCurves = (ak)? ak->totcurve: 0;
1241                         
1242                         ak= cfra_find_actkeycolumn(keys, ab->end);
1243                         endCurves = (ak)? ak->totcurve: 0;
1244                         
1245                         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
1246                         if (!startCurves && !endCurves) 
1247                                 continue;
1248                         else
1249                                 totCurves = (startCurves>endCurves)? endCurves: startCurves;
1250                                 
1251                         if (ab->totcurve >= totCurves) {
1252                                 int sc_xa, sc_ya;
1253                                 int sc_xb, sc_yb;
1254                                 
1255                                 /* get co-ordinates of block */
1256                                 gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya);
1257                                 gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb);
1258                                 
1259                                 /* draw block */
1260                                 if (ab->sel & 1)
1261                                         BIF_ThemeColor4(TH_STRIP_SELECT);
1262                                 else
1263                                         BIF_ThemeColor4(TH_STRIP);
1264                                 glRectf(sc_xa,  sc_ya-3,  sc_xb,  sc_yb+5);
1265                         }
1266                 }
1267         }
1268         
1269         /* draw keys */
1270         if (keys) {
1271                 for (ak= keys->first; ak; ak= ak->next) {
1272                         int sc_x, sc_y;
1273                         
1274                         /* get co-ordinate to draw at */
1275                         gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
1276                         
1277                         if(ak->sel & 1) BIF_icon_draw_aspect(sc_x-7, sc_y-6, ICON_SPACE2, 1.0f);
1278                         else BIF_icon_draw_aspect(sc_x-7, sc_y-6, ICON_SPACE3, 1.0f);
1279                 }       
1280         }
1281         
1282         glDisable(GL_BLEND);
1283 }
1284
1285 void draw_object_channel(gla2DDrawInfo *di, Object *ob, float ypos)
1286 {
1287         ListBase keys = {0, 0};
1288         ListBase blocks = {0, 0};
1289
1290         ob_to_keylist(ob, &keys, &blocks);
1291         draw_keylist(di, &keys, &blocks, ypos);
1292         
1293         BLI_freelistN(&keys);
1294         BLI_freelistN(&blocks);
1295 }
1296
1297 void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, float ypos)
1298 {
1299         ListBase keys = {0, 0};
1300         ListBase blocks = {0, 0};
1301
1302         ipo_to_keylist(ipo, &keys, &blocks);
1303         draw_keylist(di, &keys, &blocks, ypos);
1304         
1305         BLI_freelistN(&keys);
1306         BLI_freelistN(&blocks);
1307 }
1308
1309 void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, float ypos)
1310 {
1311         ListBase keys = {0, 0};
1312         ListBase blocks = {0, 0};
1313
1314         icu_to_keylist(icu, &keys, &blocks);
1315         draw_keylist(di, &keys, &blocks, ypos);
1316         
1317         BLI_freelistN(&keys);
1318         BLI_freelistN(&blocks);
1319 }
1320
1321 void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos)
1322 {
1323         ListBase keys = {0, 0};
1324
1325         action_to_keylist(act, &keys, NULL);
1326         draw_keylist(di, &keys, NULL, ypos);
1327         BLI_freelistN(&keys);
1328 }
1329
1330 void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks)
1331 {
1332         bConstraintChannel *conchan;
1333
1334         if (ob) {
1335                 /* Add object keyframes */
1336                 if (ob->ipo)
1337                         ipo_to_keylist(ob->ipo, keys, blocks);
1338                 
1339                 /* Add constraint keyframes */
1340                 for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
1341                         if(conchan->ipo)
1342                                 ipo_to_keylist(conchan->ipo, keys, blocks);             
1343                 }
1344                         
1345                 /* Add object data keyframes */
1346                 //              TODO??
1347         }
1348 }
1349
1350 void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks)
1351 {
1352         BezTriple *bezt;
1353         ActKeyColumn *ak;
1354         ActKeyBlock *ab;
1355         int v;
1356         
1357         if (icu && icu->totvert) {
1358                 /* loop through beztriples, making ActKeys and ActKeyBlocks */
1359                 bezt= icu->bezt;
1360                 
1361                 for (v=0; v<icu->totvert; v++, bezt++) {
1362                         add_bezt_to_keycolumnslist(keys, bezt);
1363                         if (blocks) add_bezt_to_keyblockslist(blocks, icu, v);
1364                 }
1365                 
1366                 /* update the number of curves that elements have appeared in  */
1367                 if (keys) {
1368                         for (ak= keys->first; ak; ak= ak->next) {
1369                                 if (ak->modified) {
1370                                         ak->modified = 0;
1371                                         ak->totcurve += 1;
1372                                 }
1373                         }
1374                 }
1375                 if (blocks) {
1376                         for (ab= blocks->first; ab; ab= ab->next) {
1377                                 if (ab->modified) {
1378                                         ab->modified = 0;
1379                                         ab->totcurve += 1;
1380                                 }
1381                         }
1382                 }
1383         }
1384 }
1385
1386 void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks)
1387 {
1388         IpoCurve *icu;
1389         
1390         if (ipo) {
1391                 for (icu= ipo->curve.first; icu; icu= icu->next)
1392                         icu_to_keylist(icu, keys, blocks);
1393         }
1394 }
1395
1396 void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks)
1397 {
1398         bActionChannel *achan;
1399         bConstraintChannel *conchan;
1400
1401         if (act) {
1402                 /* loop through action channels */
1403                 for (achan= act->chanbase.first; achan; achan= achan->next) {
1404                         /* firstly, add keys from action channel's ipo block */
1405                         if (achan->ipo)
1406                                 ipo_to_keylist(achan->ipo, keys, blocks);
1407                         
1408                         /* then, add keys from constraint channels */
1409                         for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
1410                                 if (conchan->ipo)
1411                                         ipo_to_keylist(achan->ipo, keys, blocks);
1412                         }
1413                 }
1414         }
1415 }
1416