== Action Editor - Individual IPO-Curves Now Shown ==
[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
67 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
68
69 #include "BIF_editaction.h"
70 #include "BIF_editkey.h"
71 #include "BIF_interface.h"
72 #include "BIF_interface_icons.h"
73 #include "BIF_gl.h"
74 #include "BIF_glutil.h"
75 #include "BIF_resources.h"
76 #include "BIF_screen.h"
77 #include "BIF_mywindow.h"
78 #include "BIF_space.h"
79
80 #include "BDR_drawaction.h"
81 #include "BDR_editcurve.h"
82
83 #include "BSE_drawnla.h"
84 #include "BSE_drawipo.h"
85 #include "BSE_editipo.h"
86 #include "BSE_time.h"
87 #include "BSE_view.h"
88
89 /* 'old' stuff": defines and types, and own include -------------------- */
90
91 #include "blendef.h"
92 #include "mydevice.h"
93
94
95 static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key)
96 {
97         int           i;
98         char          str[64];
99         float           x, y;
100         uiBlock       *block;
101         uiBut             *but;
102
103 #define XIC 20
104 #define YIC 20
105
106         /* lets make the rvk sliders */
107
108         /* reset the damn myortho2 or the sliders won't draw/redraw
109          * correctly *grumble*
110          */
111         mywinset(curarea->win);
112         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
113
114     sprintf(str, "actionbuttonswin %d", curarea->win);
115     block= uiNewBlock (&curarea->uiblocks, str, 
116                        UI_EMBOSS, UI_HELV, curarea->win);
117
118         x = NAMEWIDTH + 1;
119     y = key->totkey*(CHANNELHEIGHT+CHANNELSKIP) 
120           + CHANNELHEIGHT/2  - G.v2d->cur.ymin;
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 void draw_cfra_action(void)
176 {
177         Object *ob;
178         float vec[2];
179         
180         vec[0]= (G.scene->r.cfra);
181         vec[0]*= G.scene->r.framelen;
182         
183         vec[1]= G.v2d->cur.ymin;
184         glColor3ub(0x60, 0xc0, 0x40);
185         glLineWidth(2.0);
186         
187         glBegin(GL_LINE_STRIP);
188         glVertex2fv(vec);
189         vec[1]= G.v2d->cur.ymax;
190         glVertex2fv(vec);
191         glEnd();
192         
193         ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
194         if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
195                 vec[0]-= ob->sf;
196                 
197                 glColor3ub(0x10, 0x60, 0);
198                 
199                 glBegin(GL_LINE_STRIP);
200                 glVertex2fv(vec);
201                 vec[1]= G.v2d->cur.ymin;
202                 glVertex2fv(vec);
203                 glEnd();
204         }
205         
206         glLineWidth(1.0);
207 }
208
209 /* left hand */
210 static void draw_action_channel_names(bAction *act) 
211 {
212     bActionChannel *achan;
213     bConstraintChannel *conchan;
214         IpoCurve *icu;
215     float       x, y;
216
217     x = 0.0;
218         y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
219
220         for (achan=act->chanbase.first; achan; achan= achan->next) {
221                 if(VISIBLE_ACHAN(achan)) {
222                         glEnable(GL_BLEND);
223                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
224                         
225                         /* draw backing strip behind action channel name */
226                         BIF_ThemeColorShade(TH_HEADER, 20);
227                         glRectf(x,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
228                         
229                         /* draw expand/collapse triangle for action-channel */
230                         if (EXPANDED_ACHAN(achan))
231                                 BIF_icon_draw(x+1, y-CHANNELHEIGHT/2, ICON_TRIA_DOWN);
232                         else
233                                 BIF_icon_draw(x+1, y-CHANNELHEIGHT/2, ICON_TRIA_RIGHT);
234                         
235                         /* draw name of action channel */
236                         if (SEL_ACHAN(achan))
237                                 BIF_ThemeColor(TH_TEXT_HI);
238                         else
239                                 BIF_ThemeColor(TH_TEXT);
240                         glRasterPos2f(x+18,  y-4);
241                         BMF_DrawString(G.font, achan->name);
242                         
243                         /* draw 'lock' indicating whether channel is protected */
244                         if (EDITABLE_ACHAN(achan)==0) 
245                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
246                         else 
247                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);
248                         y-=CHANNELHEIGHT+CHANNELSKIP;
249                         
250                         if (EXPANDED_ACHAN(achan)) {
251                                 /* Draw IPO-curves show/hide widget */
252                                 if (achan->ipo) {                                       
253                                         /* draw backing strip behind */
254                                         BIF_ThemeColorShade(TH_HEADER, -20);
255                                         glRectf(x+7,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
256                                         
257                                         /* draw expand/collapse triangle for showing sub-channels  */
258                                         if (FILTER_IPO_ACHAN(achan))
259                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_DOWN);
260                                         else
261                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_RIGHT);
262                                         
263                                         /* draw icon showing type of ipo-block */
264                                         BIF_icon_draw(x+24, y-CHANNELHEIGHT/2, geticon_ipo_blocktype(achan->ipo->blocktype));
265                                         
266                                         /* draw name of ipo-block */
267                                         if (SEL_ACHAN(achan))
268                                                 BIF_ThemeColor(TH_TEXT_HI);
269                                         else
270                                                 BIF_ThemeColor(TH_TEXT);
271                                         glRasterPos2f(x+40,  y-4);
272                                         BMF_DrawString(G.font, "IPO Curves"); // TODO: make proper naming scheme
273                                 
274                                         y-=CHANNELHEIGHT+CHANNELSKIP;
275                                 
276                                         /* Draw IPO-curve-channels? */
277                                         if (FILTER_IPO_ACHAN(achan)) {
278                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
279                                                         /* draw backing strip behind ipo-curve channel*/
280                                                         BIF_ThemeColorShade(TH_HEADER, -40);
281                                                         glRectf(x+14,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
282                                                         
283                                                         /* draw name of ipo-curve channel */
284                                                         if (SEL_ICU(icu))
285                                                                 BIF_ThemeColor(TH_TEXT_HI);
286                                                         else
287                                                                 BIF_ThemeColor(TH_TEXT);
288                                                         glRasterPos2f(x+24,  y-4);
289                                                         BMF_DrawString(G.font, getname_ipocurve(icu));
290                                                         
291 #if 0 /* tempolarily disabled until all ipo-code can support this option */
292                                                         /* draw 'lock' to indicate if ipo-curve channel is protected */
293                                                         if (EDITABLE_ICU(icu)==0) 
294                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
295                                                         else 
296                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);  
297 #endif
298                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
299                                                 }
300                                         }
301                                 }
302
303                                 /* Draw constraints show/hide widget */
304                                 if (achan->constraintChannels.first) {
305                                         /* draw backing strip behind */
306                                         BIF_ThemeColorShade(TH_HEADER, -20);
307                                         glRectf(x+7,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
308                                         
309                                         /* draw expand/collapse triangle for showing sub-channels  */
310                                         if (FILTER_CON_ACHAN(achan))
311                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_DOWN);
312                                         else
313                                                 BIF_icon_draw(x+8, y-CHANNELHEIGHT/2, ICON_TRIA_RIGHT);
314                                         
315                                         /* draw constraint icon */
316                                         BIF_icon_draw(x+24, y-CHANNELHEIGHT/2, ICON_CONSTRAINT);
317                                         
318                                         /* draw name of widget */
319                                         if (SEL_ACHAN(achan))
320                                                 BIF_ThemeColor(TH_TEXT_HI);
321                                         else
322                                                 BIF_ThemeColor(TH_TEXT);
323                                         glRasterPos2f(x+40,  y-4);
324                                         BMF_DrawString(G.font, "Constraints");
325                                 
326                                         y-=CHANNELHEIGHT+CHANNELSKIP;
327                                 
328                                         /* Draw constraint channels?  */
329                                         if (FILTER_CON_ACHAN(achan)) {
330                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
331                                                         /* draw backing strip behind constraint channel*/
332                                                         BIF_ThemeColorShade(TH_HEADER, -40);
333                                                         glRectf(x+14,  y-CHANNELHEIGHT/2,  (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
334                                                         
335                                                         /* draw name of constraint channel */
336                                                         if (SEL_CONCHAN(conchan))
337                                                                 BIF_ThemeColor(TH_TEXT_HI);
338                                                         else
339                                                                 BIF_ThemeColor(TH_TEXT);
340                                                         glRasterPos2f(x+25,  y-4);
341                                                         BMF_DrawString(G.font, conchan->name);
342                                                         
343                                                         /* draw 'lock' to indicate if constraint channel is protected */
344                                                         if (EDITABLE_CONCHAN(conchan)==0) 
345                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_LOCKED);
346                                                         else 
347                                                                 BIF_icon_draw(NAMEWIDTH-16, y-CHANNELHEIGHT/2, ICON_UNLOCKED);  
348                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
349                                                 }
350                                         }
351                                 }
352                         }
353                         
354                         glDisable(GL_BLEND);
355                 }
356         }
357 }
358
359
360 static void draw_action_mesh_names(Key *key) 
361 {
362         /* draws the names of the rvk keys in the
363          * left side of the action window
364          */
365         int          i;
366         char     keyname[32];
367         float    x, y;
368         KeyBlock *kb;
369
370         x = 0.0;
371         y= key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
372
373         kb= key->block.first;
374
375         for (i=1 ; i < key->totkey ; ++ i) {
376                 glColor3ub(0xAA, 0xAA, 0xAA);
377                 glRectf(x,      y-CHANNELHEIGHT/2,      (float)NAMEWIDTH,  y+CHANNELHEIGHT/2);
378
379                 glColor3ub(0, 0, 0);
380
381                 glRasterPos2f(x+8,      y-4);
382                 kb = kb->next;
383                 /* Blender now has support for named
384                  * key blocks. If a name hasn't
385                  * been set for an key block then
386                  * just display the key number -- 
387                  * otherwise display the name stored
388                  * in the keyblock.
389                  */
390                 if (kb->name[0] == '\0') {
391                   sprintf(keyname, "Key %d", i);
392                   BMF_DrawString(G.font, keyname);
393                 }
394                 else {
395                   BMF_DrawString(G.font, kb->name);
396                 }
397
398                 y-=CHANNELHEIGHT+CHANNELSKIP;
399
400         }
401 }
402
403 /* left hand part */
404 static void draw_channel_names(void) 
405 {
406         short ofsx, ofsy = 0; 
407         bAction *act;
408         Key *key;
409
410         /* Clip to the scrollable area */
411         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
412                 if(G.v2d->scroll) {     
413                         ofsx= curarea->winrct.xmin;     
414                         ofsy= curarea->winrct.ymin;
415                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
416                                            (ofsy+G.v2d->mask.ymax) -
417                                            (ofsy+G.v2d->mask.ymin)); 
418                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
419                                           (ofsy+G.v2d->mask.ymax) -
420                                           (ofsy+G.v2d->mask.ymin));
421                 }
422         }
423         
424         myortho2(0,     NAMEWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);   //      Scaling
425         
426         glColor3ub(0x00, 0x00, 0x00);
427
428         act=G.saction->action;
429
430         if (act) {
431                 /* if there is a selected action then
432                  * draw the channel names
433                  */
434                 draw_action_channel_names(act);
435         }
436         if ( (key = get_action_mesh_key()) ) {
437                 /* if there is a mesh selected with rvk's,
438                         * then draw the RVK names
439                         */
440                 draw_action_mesh_names(key);
441     }
442
443     myortho2(0, NAMEWIDTH, 0, (ofsy+G.v2d->mask.ymax) -
444               (ofsy+G.v2d->mask.ymin)); //      Scaling
445
446 }
447
448 int count_action_levels(bAction *act)
449 {
450         bActionChannel *achan;
451         int y=0;
452
453         if (!act) 
454                 return 0;
455
456         for (achan=act->chanbase.first; achan; achan=achan->next) {
457                 if(VISIBLE_ACHAN(achan)) {
458                         y++;
459                         
460                         if (EXPANDED_ACHAN(achan)) {
461                                 if (achan->constraintChannels.first) {
462                                         y++;
463                                         if (FILTER_CON_ACHAN(achan))
464                                                 y += BLI_countlist(&achan->constraintChannels);
465                                 }
466                                 else if (achan->ipo) {
467                                         y++;
468                                         if (FILTER_IPO_ACHAN(achan))
469                                                 y += BLI_countlist(&achan->ipo->curve);
470                                 }
471                         }
472                 }
473         }
474
475         return y;
476 }
477
478 /* sets or clears hidden flags */
479 void check_action_context(SpaceAction *saction)
480 {
481         bActionChannel *achan;
482         
483         if(saction->action==NULL) return;
484         
485         for (achan=saction->action->chanbase.first; achan; achan=achan->next)
486                 achan->flag &= ~ACHAN_HIDDEN;
487         
488         if (G.saction->pin==0 && OBACT) {
489                 Object *ob= OBACT;
490                 bPoseChannel *pchan;
491                 bArmature *arm= ob->data;
492                 
493                 for (achan=saction->action->chanbase.first; achan; achan=achan->next) {
494                         pchan= get_pose_channel(ob->pose, achan->name);
495                         if(pchan)
496                                 if((pchan->bone->layer & arm->layer)==0)
497                                         achan->flag |= ACHAN_HIDDEN;
498                 }
499         }
500 }
501
502 static void draw_channel_strips(SpaceAction *saction)
503 {
504         rcti scr_rct;
505         gla2DDrawInfo *di;
506         bAction *act;
507         bActionChannel *achan;
508         bConstraintChannel *conchan;
509         IpoCurve *icu;
510         float y, sta, end;
511         int act_start, act_end, dummy;
512         char col1[3], col2[3];
513         
514         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
515         BIF_GetThemeColor3ubv(TH_HILITE, col1);
516
517         act= saction->action;
518         if (!act)
519                 return;
520
521         scr_rct.xmin= saction->area->winrct.xmin + saction->v2d.mask.xmin;
522         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
523         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
524         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
525         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
526
527         /* if in NLA there's a strip active, map the view */
528         if (G.saction->pin==0 && OBACT)
529                 map_active_strip(di, OBACT, 0);
530         
531         /* start and end of action itself */
532         calc_action_range(act, &sta, &end, 0);
533         gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
534         gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
535         
536         if (G.saction->pin==0 && OBACT)
537                 map_active_strip(di, OBACT, 1);
538         
539         /* first backdrop strips */
540         y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
541         glEnable(GL_BLEND);
542         for (achan=act->chanbase.first; achan; achan= achan->next) {
543                 if(VISIBLE_ACHAN(achan)) {
544                         int frame1_x, channel_y;
545                         
546                         gla2DDrawTranslatePt(di, G.v2d->cur.xmin, y, &frame1_x, &channel_y);
547                         
548                         if (SEL_ACHAN(achan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
549                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
550                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
551                         
552                         if (SEL_ACHAN(achan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
553                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
554                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2,  act_end,  channel_y+CHANNELHEIGHT/2);
555                         
556                         /*      Increment the step */
557                         y-=CHANNELHEIGHT+CHANNELSKIP;
558                         
559                         /* Draw sub channels */
560                         if (EXPANDED_ACHAN(achan)) {
561                                 /* Draw ipo channels */
562                                 if (achan->ipo) {
563                                         y-=CHANNELHEIGHT+CHANNELSKIP;
564                                         
565                                         if (FILTER_IPO_ACHAN(achan)) {
566                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
567                                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
568                                                         
569                                                         if (SEL_ICU(icu)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
570                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
571                                                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
572                                                         
573                                                         if (SEL_ICU(icu)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
574                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
575                                                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2+4,  act_end,  channel_y+CHANNELHEIGHT/2-4);
576                                                         
577                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
578                                                 }
579                                         }
580                                 }
581                                 
582                                 /* Draw constraint channels */
583                                 if (achan->constraintChannels.first) {
584                                         y-=CHANNELHEIGHT+CHANNELSKIP;
585                                         
586                                         if (FILTER_CON_ACHAN(achan)) {
587                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
588                                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
589                                                         
590                                                         if (SEL_CONCHAN(conchan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
591                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
592                                                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
593                                                         
594                                                         if (SEL_CONCHAN(conchan)) glColor4ub(col1[0], col1[1], col1[2], 0x22);
595                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
596                                                         glRectf(act_start,  channel_y-CHANNELHEIGHT/2+4,  act_end,  channel_y+CHANNELHEIGHT/2-4);
597                                                         
598                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
599                                                 }
600                                         }
601                                 }
602                         }
603                 }
604         }               
605         glDisable(GL_BLEND);
606         
607         if (G.saction->pin==0 && OBACT)
608                 map_active_strip(di, OBACT, 0);
609         
610         /* dot thingies */
611         y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
612         for (achan= act->chanbase.first; achan; achan= achan->next) {
613                 if(VISIBLE_ACHAN(achan)) {
614                         
615                         draw_ipo_channel(di, achan->ipo, y);
616                         y-=CHANNELHEIGHT+CHANNELSKIP;
617
618                         /* Draw sub channels */
619                         if (EXPANDED_ACHAN(achan)) {
620                                 /* Draw ipo curves */
621                                 if (achan->ipo) {
622                                         y-=CHANNELHEIGHT+CHANNELSKIP;
623                                         
624                                         if (FILTER_IPO_ACHAN(achan)) {
625                                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next) {
626                                                         draw_icu_channel(di, icu, y);
627                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
628                                                 }
629                                         }
630                                 }
631                                 
632                                 /* Draw constraint channels */
633                                 if (achan->constraintChannels.first) {
634                                         y-=CHANNELHEIGHT+CHANNELSKIP;
635                                         
636                                         if (FILTER_CON_ACHAN(achan)) {
637                                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
638                                                         draw_ipo_channel(di, conchan->ipo, y);
639                                                         y-=CHANNELHEIGHT+CHANNELSKIP;
640                                                 }
641                                         }
642                                 }
643                         }
644                 }
645         }
646
647         if(saction->flag & SACTION_MOVING) {
648                 int frame1_x, channel_y;
649                 gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &channel_y);
650                 cpack(0x0);
651                 glBegin(GL_LINES);
652                 glVertex2f(frame1_x, G.v2d->mask.ymin - 100);
653                 glVertex2f(frame1_x, G.v2d->mask.ymax);
654                 glEnd();
655         }
656         
657         glaEnd2DDraw(di);
658 }
659
660 static void draw_mesh_strips(SpaceAction *saction, Key *key)
661 {
662         /* draw the RVK keyframes as those little square button things
663          */
664         rcti scr_rct;
665         gla2DDrawInfo *di;
666         float   y, ybase;
667         IpoCurve *icu;
668         char col1[3], col2[3];
669         
670         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
671         BIF_GetThemeColor3ubv(TH_HILITE, col1);
672
673         if (!key->ipo) return;
674
675         scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
676         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
677         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
678         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
679         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
680
681         ybase = key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
682
683         for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
684
685                 int frame1_x, channel_y;
686
687                 /* lets not deal with the "speed" Ipo
688                  */
689                 if (icu->adrcode==0) continue;
690
691                 y = ybase       - (CHANNELHEIGHT+CHANNELSKIP)*(icu->adrcode-1);
692                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
693
694                 /* all frames that have a frame number less than one
695                  * get a desaturated orange background
696                  */
697                 glEnable(GL_BLEND);
698                 glColor4ub(col2[0], col2[1], col2[2], 0x22);
699                 glRectf(0,        channel_y-CHANNELHEIGHT/2,  
700                                 frame1_x, channel_y+CHANNELHEIGHT/2);
701
702                 /* frames one and higher get a saturated orange background
703                  */
704                 glColor4ub(col2[0], col2[1], col2[2], 0x44);
705                 glRectf(frame1_x,         channel_y-CHANNELHEIGHT/2,  
706                                 G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
707                 glDisable(GL_BLEND);
708
709                 /* draw the little squares
710                  */
711                 draw_icu_channel(di, icu, y); 
712         }
713
714         glaEnd2DDraw(di);
715 }
716
717 /* ********* action panel *********** */
718
719
720 void do_actionbuts(unsigned short event)
721 {
722         switch(event) {
723         case REDRAWVIEW3D:
724                 allqueue(REDRAWVIEW3D, 0);
725                 break;
726         case B_REDR:
727                 allqueue(REDRAWACTION, 0);
728                 break;
729         }
730 }
731
732
733 static void action_panel_properties(short cntrl)        // ACTION_HANDLER_PROPERTIES
734 {
735         uiBlock *block;
736
737         block= uiNewBlock(&curarea->uiblocks, "action_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
738         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
739         uiSetPanelHandler(ACTION_HANDLER_PROPERTIES);  // for close and esc
740         if(uiNewPanel(curarea, block, "Transform Properties", "Action", 10, 230, 318, 204)==0) return;
741
742         uiDefBut(block, LABEL, 0, "test text",          10,180,300,19, 0, 0, 0, 0, 0, "");
743
744 }
745
746 static void action_blockhandlers(ScrArea *sa)
747 {
748         SpaceAction *sact= sa->spacedata.first;
749         short a;
750         
751         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
752                 switch(sact->blockhandler[a]) {
753
754                 case ACTION_HANDLER_PROPERTIES:
755                         action_panel_properties(sact->blockhandler[a+1]);
756                         break;
757                 
758                 }
759                 /* clear action value for event */
760                 sact->blockhandler[a+1]= 0;
761         }
762         uiDrawBlocksPanels(sa, 0);
763 }
764
765 void drawactionspace(ScrArea *sa, void *spacedata)
766 {
767         short ofsx = 0, ofsy = 0;
768         Key *key;
769         float col[3];
770         short maxymin;
771
772         if (!G.saction)
773                 return;
774
775         /* warning; blocks need to be freed each time, handlers dont remove  */
776         uiFreeBlocksWin(&sa->uiblocks, sa->win);
777
778         if (!G.saction->pin) {
779                 /* allow more than one active action sometime? */
780                 if (OBACT)
781                         G.saction->action = OBACT->action;
782                 else
783                         G.saction->action=NULL;
784         }
785         key = get_action_mesh_key();
786
787         /* Damn I hate hunting to find my rvk's because
788          * they have scrolled off of the screen ... this
789          * oughta fix it
790          */
791         
792         if (key) {
793                 if (G.v2d->cur.ymin < -CHANNELHEIGHT) 
794                         G.v2d->cur.ymin = -CHANNELHEIGHT;
795                 
796                 maxymin = key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
797                 if (G.v2d->cur.ymin > maxymin) G.v2d->cur.ymin = maxymin;
798         }
799
800         /* Lets make sure the width of the left hand of the screen
801          * is set to an appropriate value based on whether sliders
802          * are showing of not
803          */
804         if (key && (G.saction->flag & SACTION_SLIDERS)) ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
805         else ACTWIDTH = NAMEWIDTH;
806
807         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
808
809         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
810
811         /* background color for entire window (used in lefthand part tho) */
812         BIF_GetThemeColor3fv(TH_HEADER, col);
813         glClearColor(col[0], col[1], col[2], 0.0); 
814         glClear(GL_COLOR_BUFFER_BIT);
815         
816         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
817                 if(G.v2d->scroll) {     
818                         ofsx= curarea->winrct.xmin;     
819                         ofsy= curarea->winrct.ymin;
820                         glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
821                                            ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
822                                            ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
823                         glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
824                                           ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
825                                           ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
826                 }
827         }
828
829         BIF_GetThemeColor3fv(TH_BACK, col);
830         glClearColor(col[0], col[1], col[2], 0.0);
831         glClear(GL_COLOR_BUFFER_BIT);
832
833         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
834         bwin_clear_viewmat(sa->win);    /* clear buttons view */
835         glLoadIdentity();
836
837         /*      Draw backdrop */
838         calc_ipogrid(); 
839         draw_ipogrid();
840
841         check_action_context(G.saction);
842         
843         /* Draw channel strips */
844         draw_channel_strips(G.saction);
845
846         if (key) {
847                 /* if there is a mesh with rvk's selected,
848                  * then draw the key frames in the action window
849                  */
850                 draw_mesh_strips(G.saction, key);
851         }
852         
853         /* reset matrices for stuff to be drawn on top of keys*/
854         glViewport(ofsx+G.v2d->mask.xmin,  
855              ofsy+G.v2d->mask.ymin, 
856              ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
857              ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
858         glScissor(ofsx+G.v2d->mask.xmin,  
859             ofsy+G.v2d->mask.ymin, 
860             ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
861             ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
862         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax,  G.v2d->cur.ymin, G.v2d->cur.ymax);
863         
864         /* Draw current frame */
865         draw_cfra_action();
866         
867         /* Draw markers */
868         draw_markers_timespace();
869         
870         /* Draw 'curtains' for preview */
871         draw_anim_preview_timespace();
872
873         /* Draw scroll */
874         mywinset(curarea->win); // reset scissor too
875         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
876       myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
877       if(G.v2d->scroll) drawscroll(0);
878         }
879
880         if(G.v2d->mask.xmin!=0) {
881                 /* Draw channel names */
882                 draw_channel_names();
883
884                 if(sa->winx > 50 + NAMEWIDTH + SLIDERWIDTH) {
885                         if ( key ) {
886                                 /* if there is a mesh with rvk's selected,
887                                  * then draw the key frames in the action window
888                                  */
889                                 meshactionbuts(G.saction, OBACT, key);
890                         }
891                 }
892         }
893         
894         mywinset(curarea->win); // reset scissor too
895         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
896         draw_area_emboss(sa);
897
898         /* it is important to end a view in a transform compatible with buttons */
899         bwin_scalematrix(sa->win, G.saction->blockscale, G.saction->blockscale, G.saction->blockscale);
900         action_blockhandlers(sa);
901
902         curarea->win_swap= WIN_BACK_OK;
903 }
904
905 static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos, int totcurve)
906 {
907         CfraElem *ce;
908         ActKeyBlock *ab;
909         
910         glEnable(GL_BLEND);
911         
912         /* draw keyblocks */
913         if (blocks) {
914                 for (ab= blocks->first; ab; ab= ab->next) {
915                         /* only draw keyblock if it appears in all curves sampled */
916                         if (ab->totcurve == totcurve) {
917                                 int sc_xa, sc_ya;
918                                 int sc_xb, sc_yb;
919                                 
920                                 /* get co-ordinates of block */
921                                 gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya);
922                                 gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb);
923                                 
924                                 /* draw block */
925                                 if (ab->sel & 1)
926                                         BIF_ThemeColor4(TH_STRIP_SELECT);
927                                 else
928                                         BIF_ThemeColor4(TH_STRIP);
929                                 glRectf(sc_xa,  sc_ya-3,  sc_xb,  sc_yb+5);
930                         }
931                 }
932         }
933         
934         /* draw keys */
935         if (keys) {
936                 for (ce= keys->first; ce; ce= ce->next) {
937                         int sc_x, sc_y;
938                         
939                         /* get co-ordinate to draw at */
940                         gla2DDrawTranslatePt(di, ce->cfra, ypos, &sc_x, &sc_y);
941                         
942                         if(ce->sel & 1) BIF_icon_draw_aspect(sc_x-7, sc_y-6, ICON_SPACE2, 1.0f);
943                         else BIF_icon_draw_aspect(sc_x-7, sc_y-6, ICON_SPACE3, 1.0f);
944                 }       
945         }
946         
947         glDisable(GL_BLEND);
948 }
949
950 void draw_object_channel(gla2DDrawInfo *di, Object *ob, float ypos)
951 {
952         ListBase keys = {0, 0};
953         ListBase blocks = {0, 0};
954         int totcurve;
955
956         totcurve= ob_to_keylist(ob, &keys, &blocks);
957         draw_keylist(di, &keys, &blocks, ypos, totcurve);
958         
959         BLI_freelistN(&keys);
960         BLI_freelistN(&blocks);
961 }
962
963 void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, float ypos)
964 {
965         ListBase keys = {0, 0};
966         ListBase blocks = {0, 0};
967         int totcurve;
968
969         totcurve= ipo_to_keylist(ipo, &keys, &blocks);
970         draw_keylist(di, &keys, &blocks, ypos, totcurve);
971         
972         BLI_freelistN(&keys);
973         BLI_freelistN(&blocks);
974 }
975
976 void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, float ypos)
977 {
978         ListBase keys = {0, 0};
979         ListBase blocks = {0, 0};
980
981         icu_to_keylist(icu, &keys, &blocks);
982         draw_keylist(di, &keys, &blocks, ypos, 1);
983         
984         BLI_freelistN(&keys);
985         BLI_freelistN(&blocks);
986 }
987
988 void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos)
989 {
990         ListBase keys = {0, 0};
991
992         action_to_keylist(act, &keys, NULL);
993         draw_keylist(di, &keys, NULL, ypos, 0);
994         BLI_freelistN(&keys);
995 }
996
997 static void add_bezt_to_keyblockslist(ListBase *blocks, IpoCurve *icu, int index)
998 {
999         /* The equivilant of add_to_cfra_elem except this version 
1000          * makes ActKeyBlocks - one of the two datatypes required
1001          * for action editor drawing.
1002          */
1003         ActKeyBlock *ab, *abn;
1004         BezTriple *beztn=NULL, *prev=NULL;
1005         BezTriple *bezt;
1006         int v;
1007         
1008         /* get beztriples */
1009         beztn= (icu->bezt + index);
1010         /* The following search for previous beztriple doesn't work
1011          * that great on actions with a large amount of keys. There
1012          * are a few commented out shortcuts for these cases, which will
1013          * remain so until the definitive point where slowdown starts to
1014          * bite is determined.
1015          */
1016         //if (icu->totvert > 3500) {
1017         //      if (index >= 1) 
1018         //              prev= (icu->bezt + (index - 1));
1019         //}
1020         //else {
1021                 for (v=0, bezt=icu->bezt; v<icu->totvert; v++, bezt++) {
1022                         /* skip if beztriple is current */
1023                         if (v != index) {
1024                                 /* check if beztriple is immediately before */
1025                                 if (beztn->vec[1][0] > bezt->vec[1][0]) {
1026                                         /* check if closer than previous was */
1027                                         if (prev) {
1028                                                 if (prev->vec[1][0] < bezt->vec[1][0])
1029                                                         prev= bezt;
1030                                         }
1031                                         else {
1032                                                 prev= bezt;
1033                                         }
1034                                 }
1035                         }
1036                 }
1037         //}
1038         
1039         /* check if block needed - same value? */
1040         if ((!prev) || (!beztn))
1041                 return;
1042         if (beztn->vec[1][1] != prev->vec[1][1])
1043                 return;
1044         
1045         /* try to find a keyblock that starts on the previous beztriple */
1046         for (ab= blocks->first; ab; ab= ab->next) {
1047                 /* check if alter existing block or add new block */
1048                 if (ab->start == prev->vec[1][0]) {                     
1049                         /* set selection status and 'touched' status */
1050                         if (BEZSELECTED(beztn)) ab->sel = SELECT;
1051                         ab->modified += 1;
1052                         
1053                         return;
1054                 }
1055                 else if (ab->start > prev->vec[1][0]) break;
1056         }
1057         
1058         /* add new block */
1059         abn= MEM_callocN(sizeof(ActKeyBlock), "add_bezt_to_keyblockslist");
1060         if (ab) BLI_insertlinkbefore(blocks, ab, abn);
1061         else BLI_addtail(blocks, abn);
1062         
1063         abn->start= prev->vec[1][0];
1064         abn->end= beztn->vec[1][0];
1065         abn->val= beztn->vec[1][1];
1066         
1067         if (BEZSELECTED(prev) || BEZSELECTED(beztn))
1068                 abn->sel = SELECT;
1069         else
1070                 abn->sel = 0;
1071         abn->modified += 1;
1072 }
1073
1074 int ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks)
1075 {
1076         bConstraintChannel *conchan;
1077         int totcurve = 0;
1078
1079         if (ob) {
1080                 /* Add object keyframes */
1081                 if (ob->ipo) {
1082                         totcurve += ipo_to_keylist(ob->ipo, keys, blocks);
1083                 }
1084                 
1085                 /* Add constraint keyframes */
1086                 for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
1087                         if(conchan->ipo) {
1088                                 totcurve += ipo_to_keylist(conchan->ipo, keys, blocks);
1089                         }                               
1090                 }
1091                         
1092                 /* Add object data keyframes */
1093                 //              TODO??
1094         }
1095         
1096         return totcurve;
1097 }
1098
1099 void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks)
1100 {
1101         BezTriple *bezt;
1102         ActKeyBlock *ab, *abn;
1103         int v;
1104         
1105         if (icu && icu->totvert) {
1106                 /* loop through beztriples, making ActKeys and ActKeyBlocks */
1107                 bezt= icu->bezt;
1108                 
1109                 for (v=0; v<icu->totvert; v++, bezt++) {
1110                         add_to_cfra_elem(keys, bezt);
1111                         if (blocks) add_bezt_to_keyblockslist(blocks, icu, v);
1112                 }
1113                 
1114                 /* update the number of curves the blocks have appeared in */
1115                 if (blocks) {
1116                         for (ab= blocks->first; ab; ab= abn) {
1117                                 abn= ab->next;
1118                                 
1119                                 if (ab->modified) {
1120                                         ab->modified = 0;
1121                                         ab->totcurve += 1;
1122                                 }
1123                         }
1124                 }
1125         }
1126 }
1127
1128 int ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks)
1129 {
1130         IpoCurve *icu;
1131         int totcurve = 0;
1132         
1133         if (ipo) {
1134                 for (icu= ipo->curve.first; icu; icu= icu->next) {
1135                         icu_to_keylist(icu, keys, blocks);
1136                         totcurve++;
1137                 }
1138         }
1139         
1140         return totcurve;
1141 }
1142
1143 int action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks)
1144 {
1145         bActionChannel *achan;
1146         bConstraintChannel *conchan;
1147         int totcurve = 0;
1148
1149         if (act) {
1150                 /* loop through action channels */
1151                 for (achan= act->chanbase.first; achan; achan= achan->next) {
1152                         /* firstly, add keys from action channel's ipo block */
1153                         if (achan->ipo) {
1154                                 totcurve+= ipo_to_keylist(achan->ipo, keys, blocks);
1155                         }
1156                         
1157                         /* then, add keys from constraint channels */
1158                         for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
1159                                 if (conchan->ipo) {
1160                                         totcurve+= ipo_to_keylist(achan->ipo, keys, blocks);
1161                                 }
1162                         }
1163                 }
1164         }
1165         
1166         return totcurve;
1167 }
1168