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