soc-2008-mxcurioni: merged changes to revision 15705
[blender.git] / source / blender / src / drawaction.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * Drawing routines for the Action window type
29  */
30
31 /* System includes ----------------------------------------------------- */
32
33 #include <math.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BMF_Api.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_arithb.h"
47
48 /* Types --------------------------------------------------------------- */
49 #include "DNA_listBase.h"
50 #include "DNA_action_types.h"
51 #include "DNA_armature_types.h"
52 #include "DNA_curve_types.h"
53 #include "DNA_ipo_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_screen_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_space_types.h"
58 #include "DNA_constraint_types.h"
59 #include "DNA_key_types.h"
60 #include "DNA_userdef_types.h"
61 #include "DNA_gpencil_types.h"
62
63 #include "BKE_action.h"
64 #include "BKE_depsgraph.h"
65 #include "BKE_ipo.h"
66 #include "BKE_key.h"
67 #include "BKE_object.h"
68 #include "BKE_global.h"
69 #include "BKE_utildefines.h"
70
71 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
72
73 #include "BIF_editaction.h"
74 #include "BIF_editkey.h"
75 #include "BIF_editnla.h"
76 #include "BIF_interface.h"
77 #include "BIF_interface_icons.h"
78 #include "BIF_drawgpencil.h"
79 #include "BIF_gl.h"
80 #include "BIF_glutil.h"
81 #include "BIF_resources.h"
82 #include "BIF_screen.h"
83 #include "BIF_mywindow.h"
84 #include "BIF_space.h"
85
86 #include "BDR_drawaction.h"
87 #include "BDR_editcurve.h"
88 #include "BDR_gpencil.h"
89
90 #include "BSE_drawnla.h"
91 #include "BSE_drawipo.h"
92 #include "BSE_editaction_types.h"
93 #include "BSE_editipo.h"
94 #include "BSE_time.h"
95 #include "BSE_view.h"
96
97 /* 'old' stuff": defines and types, and own include -------------------- */
98
99 #include "blendef.h"
100 #include "interface.h"
101 #include "mydevice.h"
102
103 /********************************** Slider Stuff **************************** */
104
105 /* sliders for shapekeys */
106 static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key)
107 {
108         int           i;
109         char          str[64];
110         float         x, y;
111         uiBlock       *block;
112         uiBut             *but;
113
114 #define XIC 20
115 #define YIC 20
116
117         /* lets make the rvk sliders */
118
119         /* reset the damn myortho2 or the sliders won't draw/redraw
120          * correctly *grumble*
121          */
122         mywinset(curarea->win);
123         myortho2(-0.375, curarea->winx-0.375, G.v2d->cur.ymin, G.v2d->cur.ymax);
124
125     sprintf(str, "actionbuttonswin %d", curarea->win);
126     block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSS, UI_HELV, curarea->win);
127
128         x = NAMEWIDTH + 1;
129     y = 0.0f;
130
131         /* make the little 'open the sliders' widget */
132         // should eventually be removed
133     BIF_ThemeColor(TH_FACE); // this slot was open... (???... Aligorith)
134         glRects(2,            y + 2*CHANNELHEIGHT - 2, ACTWIDTH - 2, y + CHANNELHEIGHT + 2);
135         glColor3ub(0, 0, 0);
136         glRasterPos2f(4, y + CHANNELHEIGHT + 6);
137         BMF_DrawString(G.font, "Sliders");
138
139         uiBlockSetEmboss(block, UI_EMBOSSN);
140
141         if (!(G.saction->flag & SACTION_SLIDERS)) {
142                 ACTWIDTH = NAMEWIDTH;
143                 but=uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR, 
144                                           ICON_DISCLOSURE_TRI_RIGHT,
145                                           NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
146                                           XIC,YIC-2,
147                                           &(G.saction->flag), 0, 0, 0, 0, 
148                                           "Show action window sliders");
149                 /* no hilite, the winmatrix is not correct later on... */
150                 uiButSetFlag(but, UI_NO_HILITE);
151
152         }
153         else {
154                 but= uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR, 
155                                           ICON_DISCLOSURE_TRI_DOWN,
156                                           NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
157                                           XIC,YIC-2,
158                                           &(G.saction->flag), 0, 0, 0, 0, 
159                                           "Hide action window sliders");
160                 /* no hilite, the winmatrix is not correct later on... */
161                 uiButSetFlag(but, UI_NO_HILITE);
162                                           
163                 ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
164
165                 /* sliders are open so draw them */
166                 BIF_ThemeColor(TH_FACE); 
167
168                 glRects(NAMEWIDTH,  0,  NAMEWIDTH+SLIDERWIDTH,  curarea->winy);
169                 uiBlockSetEmboss(block, UI_EMBOSS);
170                 for (i=1; i < key->totkey; i++) {
171                         make_rvk_slider(block, ob, i, 
172                                                         x, y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
173                         
174                         y-=CHANNELHEIGHT+CHANNELSKIP;
175                         
176                         /* see sliderval array in editkey.c */
177                         if(i >= 255) break;
178                 }
179         }
180         uiDrawBlock(block);
181 }
182
183 static void icu_slider_func(void *voidicu, void *voidignore) 
184 {
185         /* the callback for the icu sliders ... copies the
186          * value from the icu->curval into a bezier at the
187          * right frame on the right ipo curve (creating both the
188          * ipo curve and the bezier if needed).
189          */
190         IpoCurve  *icu= voidicu;
191         BezTriple *bezt=NULL;
192         float cfra, icuval;
193
194         cfra = frame_to_float(CFRA);
195         if (G.saction->pin==0 && OBACT)
196                 cfra= get_action_frame(OBACT, cfra);
197         
198         /* if the ipocurve exists, try to get a bezier
199          * for this frame
200          */
201         bezt = get_bezt_icu_time(icu, &cfra, &icuval);
202
203         /* create the bezier triple if one doesn't exist,
204          * otherwise modify it's value
205          */
206         if (bezt == NULL) {
207                 insert_vert_icu(icu, cfra, icu->curval, 0);
208         }
209         else {
210                 bezt->vec[1][1] = icu->curval;
211         }
212
213         /* make sure the Ipo's are properly processed and
214          * redraw as necessary
215          */
216         sort_time_ipocurve(icu);
217         testhandles_ipocurve(icu);
218         
219         /* nla-update (in case this affects anything) */
220         synchronize_action_strips();
221         
222         /* do redraw pushes, and also the depsgraph flushes */
223         if (OBACT->pose || ob_get_key(OBACT))
224                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC);
225         else
226                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB);
227         
228         allqueue(REDRAWVIEW3D, 0);
229         allqueue(REDRAWACTION, 0);
230         allqueue(REDRAWNLA, 0);
231         allqueue(REDRAWIPO, 0);
232         allspace(REMAKEIPO, 0);
233         allqueue(REDRAWBUTSALL, 0);
234 }
235
236 static void make_icu_slider(uiBlock *block, IpoCurve *icu,
237                                          int x, int y, int w, int h, char *tip)
238 {
239         /* create a slider for the ipo-curve*/
240         uiBut *but;
241         
242         if(icu == NULL) return;
243         
244         if (IS_EQ(icu->slide_max, icu->slide_min)) {
245                 if (IS_EQ(icu->ymax, icu->ymin)) {
246                         if (ELEM(icu->blocktype, ID_CO, ID_KE)) {
247                                 /* hack for constraints and shapekeys (and maybe a few others) */
248                                 icu->slide_min= 0.0;
249                                 icu->slide_max= 1.0;
250                         }
251                         else {
252                                 icu->slide_min= -100;
253                                 icu->slide_max= 100;
254                         }
255                 }
256                 else {
257                         icu->slide_min= icu->ymin;
258                         icu->slide_max= icu->ymax;
259                 }
260         }
261         if (icu->slide_min >= icu->slide_max) {
262                 SWAP(float, icu->slide_min, icu->slide_max);
263         }
264
265         but=uiDefButF(block, NUMSLI, REDRAWVIEW3D, "",
266                                   x, y , w, h,
267                                   &(icu->curval), icu->slide_min, icu->slide_max, 
268                                   10, 2, tip);
269         
270         uiButSetFunc(but, icu_slider_func, icu, NULL);
271         
272         // no hilite, the winmatrix is not correct later on...
273         uiButSetFlag(but, UI_NO_HILITE);
274 }
275
276 /* sliders for ipo-curves of active action-channel */
277 static void action_icu_buts(SpaceAction *saction)
278 {
279         ListBase act_data = {NULL, NULL};
280         bActListElem *ale;
281         int filter;
282         void *data;
283         short datatype;
284         
285         char          str[64];
286         float           x, y;
287         uiBlock       *block;
288
289         /* lets make the action sliders */
290
291         /* reset the damn myortho2 or the sliders won't draw/redraw
292          * correctly *grumble*
293          */
294         mywinset(curarea->win);
295         myortho2(-0.375, curarea->winx-0.375, G.v2d->cur.ymin, G.v2d->cur.ymax);
296         
297     sprintf(str, "actionbuttonswin %d", curarea->win);
298     block= uiNewBlock (&curarea->uiblocks, str, 
299                        UI_EMBOSS, UI_HELV, curarea->win);
300
301         x = NAMEWIDTH + 1;
302     y = 0.0f;
303         
304         uiBlockSetEmboss(block, UI_EMBOSSN);
305
306         if (G.saction->flag & SACTION_SLIDERS) {
307                 /* sliders are open so draw them */
308                 
309                 /* get editor data */
310                 data= get_action_context(&datatype);
311                 if (data == NULL) return;
312                 
313                 /* build list of channels to draw */
314                 filter= (ACTFILTER_FORDRAWING|ACTFILTER_VISIBLE|ACTFILTER_CHANNELS);
315                 actdata_filter(&act_data, filter, data, datatype);
316                 
317                 /* draw backdrop first */
318                 BIF_ThemeColor(TH_FACE); // change this color... it's ugly
319                 glRects(NAMEWIDTH,  G.v2d->cur.ymin,  NAMEWIDTH+SLIDERWIDTH,  G.v2d->cur.ymax);
320                 
321                 uiBlockSetEmboss(block, UI_EMBOSS);
322                 for (ale= act_data.first; ale; ale= ale->next) {
323                         const float yminc= y-CHANNELHEIGHT/2;
324                         const float ymaxc= y+CHANNELHEIGHT/2;
325                         
326                         /* check if visible */
327                         if ( IN_RANGE(yminc, G.v2d->cur.ymin, G.v2d->cur.ymax) ||
328                                  IN_RANGE(ymaxc, G.v2d->cur.ymin, G.v2d->cur.ymax) ) 
329                         {
330                                 /* determine what needs to be drawn */
331                                 switch (ale->type) {
332                                         case ACTTYPE_CONCHAN: /* constraint channel */
333                                         {
334                                                 bActionChannel *achan = (bActionChannel *)ale->owner;
335                                                 IpoCurve *icu = (IpoCurve *)ale->key_data;
336                                                 
337                                                 /* only show if action channel is selected */
338                                                 if (SEL_ACHAN(achan)) {
339                                                         make_icu_slider(block, icu,
340                                                                                         x, y, SLIDERWIDTH-2, CHANNELHEIGHT-2, 
341                                                                                         "Slider to control current value of Constraint Influence");
342                                                 }
343                                         }
344                                                 break;
345                                         case ACTTYPE_ICU: /* ipo-curve channel */
346                                         {
347                                                 bActionChannel *achan = (bActionChannel *)ale->owner;
348                                                 IpoCurve *icu = (IpoCurve *)ale->key_data;
349                                                 
350                                                 /* only show if action channel is selected */
351                                                 if (SEL_ACHAN(achan)) {
352                                                         make_icu_slider(block, icu,
353                                                                                         x, y, SLIDERWIDTH-2, CHANNELHEIGHT-2, 
354                                                                                         "Slider to control current value of IPO-Curve");
355                                                 }
356                                         }
357                                                 break;
358                                         case ACTTYPE_SHAPEKEY: /* shapekey channel */
359                                         {
360                                                 // TODO...
361                                         }
362                                                 break;
363                                 }
364                         }
365                         
366                         /* adjust y-position for next one */
367                         y-=CHANNELHEIGHT+CHANNELSKIP;
368                 }
369                 
370                 /* free tempolary channels */
371                 BLI_freelistN(&act_data);
372         }
373         uiDrawBlock(block);
374 }
375
376 /********************************** Current Frame **************************** */
377
378 void draw_cfra_action (void)
379 {
380         Object *ob;
381         float vec[2];
382         
383         /* Draw a light green line to indicate current frame */
384         vec[0]= (G.scene->r.cfra);
385         vec[0]*= G.scene->r.framelen;
386         
387         vec[1]= G.v2d->cur.ymin;
388         BIF_ThemeColor(TH_CFRAME);
389         glLineWidth(2.0);
390         
391         glBegin(GL_LINE_STRIP);
392         glVertex2fv(vec);
393         vec[1]= G.v2d->cur.ymax;
394         glVertex2fv(vec);
395         glEnd();
396         
397         /* Draw dark green line if slow-parenting/time-offset is enabled */
398         ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
399         if ((ob) && (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0)) {
400                 vec[0]-= give_timeoffset(ob); /* could avoid calling twice */
401                 
402                 BIF_ThemeColorShade(TH_CFRAME, -30);
403                 
404                 glBegin(GL_LINE_STRIP);
405                 glVertex2fv(vec);
406                 vec[1]= G.v2d->cur.ymin;
407                 glVertex2fv(vec);
408                 glEnd();
409         }
410         
411         glLineWidth(1.0);
412 }
413
414 /********************************** Left-Hand Panel + Generics **************************** */
415
416 /* left hand part */
417 static void draw_channel_names(void) 
418 {
419         ListBase act_data = {NULL, NULL};
420         bActListElem *ale;
421         int filter;
422         void *data;
423         short datatype;
424         short ofsx = 0, ofsy = 0; 
425         float x= 0.0f, y= 0.0f;
426         
427         /* determine what type of data we are operating on */
428         data = get_action_context(&datatype);
429         if (data == NULL) return;
430         
431         /* Clip to the scrollable area */
432         if (curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
433                 if(G.v2d->scroll) {     
434                         ofsx= curarea->winrct.xmin;     
435                         ofsy= curarea->winrct.ymin;
436                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
437                                            (ofsy+G.v2d->mask.ymax) -
438                                            (ofsy+G.v2d->mask.ymin)); 
439                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin, NAMEWIDTH, 
440                                           (ofsy+G.v2d->mask.ymax) -
441                                           (ofsy+G.v2d->mask.ymin));
442                 }
443         }
444         
445         /* prepare scaling for LHS panel */
446         myortho2(0,     NAMEWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);
447         
448         /* set default color back to black */
449         glColor3ub(0x00, 0x00, 0x00);
450         
451         /* build list of channels to draw */
452         filter= (ACTFILTER_FORDRAWING|ACTFILTER_VISIBLE|ACTFILTER_CHANNELS);
453         actdata_filter(&act_data, filter, data, datatype);
454         
455         /* loop through channels, and set up drawing depending on their type  */
456         glEnable(GL_BLEND);
457         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
458         
459         for (ale= act_data.first; ale; ale= ale->next) {
460                 const float yminc= y-CHANNELHEIGHT/2;
461                 const float ymaxc= y+CHANNELHEIGHT/2;
462                 
463                 /* check if visible */
464                 if ( IN_RANGE(yminc, G.v2d->cur.ymin, G.v2d->cur.ymax) ||
465                          IN_RANGE(ymaxc, G.v2d->cur.ymin, G.v2d->cur.ymax) ) 
466                 {
467                         bActionGroup *grp = NULL;
468                         short indent= 0, offset= 0, sel= 0, group=0;
469                         int expand= -1, protect = -1, special= -1, mute = -1;
470                         char name[32];
471                         
472                         /* determine what needs to be drawn */
473                         switch (ale->type) {
474                                 case ACTTYPE_GROUP: /* action group */
475                                 {
476                                         bActionGroup *agrp= (bActionGroup *)ale->data;
477                                         
478                                         group= 2;
479                                         indent= 0;
480                                         special= -1;
481                                         
482                                         /* only show expand if there are any channels */
483                                         if (agrp->channels.first) {
484                                                 if (EXPANDED_AGRP(agrp))
485                                                         expand = ICON_TRIA_DOWN;
486                                                 else
487                                                         expand = ICON_TRIA_RIGHT;
488                                         }
489                                                 
490                                         if (EDITABLE_AGRP(agrp))
491                                                 protect = ICON_UNLOCKED;
492                                         else
493                                                 protect = ICON_LOCKED;
494                                                 
495                                         sel = SEL_AGRP(agrp);
496                                         sprintf(name, agrp->name);
497                                 }
498                                         break;
499                                 case ACTTYPE_ACHAN: /* action channel */
500                                 {
501                                         bActionChannel *achan= (bActionChannel *)ale->data;
502                                         
503                                         group= (ale->grp) ? 1 : 0;
504                                         grp= ale->grp;
505                                         
506                                         indent = 0;
507                                         special = -1;
508                                         
509                                         if (EXPANDED_ACHAN(achan))
510                                                 expand = ICON_TRIA_DOWN;
511                                         else
512                                                 expand = ICON_TRIA_RIGHT;
513                                                 
514                                         if (EDITABLE_ACHAN(achan))
515                                                 protect = ICON_UNLOCKED;
516                                         else
517                                                 protect = ICON_LOCKED;
518                                                 
519                                         if (achan->ipo) {
520                                                 if (achan->ipo->muteipo)
521                                                         mute = ICON_MUTE_IPO_ON;
522                                                 else
523                                                         mute = ICON_MUTE_IPO_OFF;
524                                         }
525                                         
526                                         sel = SEL_ACHAN(achan);
527                                         sprintf(name, achan->name);
528                                 }
529                                         break;
530                                 case ACTTYPE_CONCHAN: /* constraint channel */
531                                 {
532                                         bConstraintChannel *conchan = (bConstraintChannel *)ale->data;
533                                         
534                                         indent = 2;
535                                         
536                                         group= (ale->grp) ? 1 : 0;
537                                         grp= ale->grp;
538                                         
539                                         if (EDITABLE_CONCHAN(conchan))
540                                                 protect = ICON_UNLOCKED;
541                                         else
542                                                 protect = ICON_LOCKED;
543                                                 
544                                         if (conchan->ipo) {
545                                                 if (conchan->ipo->muteipo)
546                                                         mute = ICON_MUTE_IPO_ON;
547                                                 else
548                                                         mute = ICON_MUTE_IPO_OFF;
549                                         }
550                                         
551                                         sel = SEL_CONCHAN(conchan);
552                                         sprintf(name, conchan->name);
553                                 }
554                                         break;
555                                 case ACTTYPE_ICU: /* ipo-curve channel */
556                                 {
557                                         IpoCurve *icu = (IpoCurve *)ale->data;
558                                         
559                                         indent = 2;
560                                         protect = -1; // for now, until this can be supported by others
561                                         
562                                         group= (ale->grp) ? 1 : 0;
563                                         grp= ale->grp;
564                                         
565                                         if (icu->flag & IPO_MUTE)
566                                                 mute = ICON_MUTE_IPO_ON;
567                                         else    
568                                                 mute = ICON_MUTE_IPO_OFF;
569                                         
570                                         sel = SEL_ICU(icu);
571                                         if (G.saction->pin)
572                                                 sprintf(name, getname_ipocurve(icu, NULL));
573                                         else
574                                                 sprintf(name, getname_ipocurve(icu, OBACT));
575                                 }
576                                         break;
577                                 case ACTTYPE_SHAPEKEY: /* shapekey channel */
578                                 {
579                                         KeyBlock *kb = (KeyBlock *)ale->data;
580                                         
581                                         indent = 0;
582                                         special = -1;
583                                         
584                                         if (kb->name[0] == '\0')
585                                                 sprintf(name, "Key %d", ale->index);
586                                         else
587                                                 sprintf(name, kb->name);
588                                 }
589                                         break;
590                                 case ACTTYPE_FILLIPO: /* ipo expand widget */
591                                 {
592                                         bActionChannel *achan = (bActionChannel *)ale->data;
593                                         
594                                         indent = 1;
595                                         special = geticon_ipo_blocktype(achan->ipo->blocktype);
596                                         
597                                         group= (ale->grp) ? 1 : 0;
598                                         grp= ale->grp;
599                                         
600                                         if (FILTER_IPO_ACHAN(achan))    
601                                                 expand = ICON_TRIA_DOWN;
602                                         else
603                                                 expand = ICON_TRIA_RIGHT;
604                                         
605                                         sel = SEL_ACHAN(achan);
606                                         sprintf(name, "IPO Curves");
607                                 }
608                                         break;
609                                 case ACTTYPE_FILLCON: /* constraint expand widget */
610                                 {
611                                         bActionChannel *achan = (bActionChannel *)ale->data;
612                                         
613                                         indent = 1;
614                                         special = ICON_CONSTRAINT;
615                                         
616                                         group= (ale->grp) ? 1 : 0;
617                                         grp= ale->grp;
618                                         
619                                         if (FILTER_CON_ACHAN(achan))    
620                                                 expand = ICON_TRIA_DOWN;
621                                         else
622                                                 expand = ICON_TRIA_RIGHT;
623                                                 
624                                         sel = SEL_ACHAN(achan);
625                                         sprintf(name, "Constraint");
626                                 }
627                                         break;
628                                 case ACTTYPE_GPLAYER: /* gpencil layer */
629                                 {
630                                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
631                                         
632                                         indent = 0;
633                                         special = -1;
634                                         expand = -1;
635                                                 
636                                         if (EDITABLE_GPL(gpl))
637                                                 protect = ICON_UNLOCKED;
638                                         else
639                                                 protect = ICON_LOCKED;
640                                                 
641                                         if (gpl->flag & GP_LAYER_HIDE)
642                                                 mute = ICON_MUTE_IPO_ON;
643                                         else
644                                                 mute = ICON_MUTE_IPO_OFF;
645                                         
646                                         sel = SEL_GPL(gpl);
647                                         BLI_snprintf(name, 32, gpl->info);
648                                 }
649                                         break;
650                         }       
651
652                         /* now, start drawing based on this information */
653                         /* draw backing strip behind channel name */
654                         if (group == 2) {
655                                 /* only for group-channels */
656                                 if (ale->flag & AGRP_ACTIVE)
657                                         BIF_ThemeColorShade(TH_GROUP_ACTIVE, 10);
658                                 else
659                                         BIF_ThemeColorShade(TH_GROUP, 20);
660                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
661                                 gl_round_box(GL_POLYGON, x,  yminc, (float)NAMEWIDTH, ymaxc, 8);
662                                 
663                                 offset = 0;
664                         }
665                         else {
666                                 /* for normal channels 
667                                  *      - use 3 shades of color group/standard color for 3 indention level
668                                  *      - only use group colors if allowed to, and if actually feasible
669                                  */
670                                 if ( !(G.saction->flag & SACTION_NODRAWGCOLORS) && 
671                                          (grp) && (grp->customCol) ) 
672                                 {
673                                         char cp[3];
674                                         
675                                         if (indent == 2) {
676                                                 VECCOPY(cp, grp->cs.solid);
677                                         }
678                                         else if (indent == 1) {
679                                                 VECCOPY(cp, grp->cs.select);
680                                         }
681                                         else {
682                                                 VECCOPY(cp, grp->cs.active);
683                                         }
684                                         
685                                         glColor3ub(cp[0], cp[1], cp[2]);
686                                 }
687                                 else
688                                         BIF_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
689                                 
690                                 indent += group;
691                                 offset = 7 * indent;
692                                 glRectf(x+offset,  yminc, (float)NAMEWIDTH, ymaxc);
693                         }
694                         
695                         /* draw expand/collapse triangle */
696                         if (expand > 0) {
697                                 BIF_icon_draw(x+offset, yminc, expand);
698                                 offset += 17;
699                         }
700                         
701                         /* draw special icon indicating type of ipo-blocktype? 
702                          *      only for expand widgets for Ipo and Constraint Channels 
703                          */
704                         if (special > 0) {
705                                 offset = (group) ? 29 : 24;
706                                 BIF_icon_draw(x+offset, yminc, special);
707                                 offset += 17;
708                         }
709                                 
710                         /* draw name */
711                         if (sel)
712                                 BIF_ThemeColor(TH_TEXT_HI);
713                         else
714                                 BIF_ThemeColor(TH_TEXT);
715                         offset += 3;
716                         glRasterPos2f(x+offset, y-4);
717                         BMF_DrawString(G.font, name);
718                         
719                         /* reset offset - for RHS of panel */
720                         offset = 0;
721                         
722                         /* draw protect 'lock' */
723                         if (protect > 0) {
724                                 offset = 16;
725                                 BIF_icon_draw(NAMEWIDTH-offset, yminc, protect);
726                         }
727                         
728                         /* draw mute 'eye' */
729                         if (mute > 0) {
730                                 offset += 16;
731                                 BIF_icon_draw(NAMEWIDTH-offset, yminc, mute);
732                         }
733                 }
734                 
735                 /* adjust y-position for next one */
736                 y-=CHANNELHEIGHT+CHANNELSKIP;
737         }
738         
739         /* free tempolary channels */
740         BLI_freelistN(&act_data);
741         
742         /* re-adjust view matrices for correct scaling */
743     myortho2(0, NAMEWIDTH, 0, (ofsy+G.v2d->mask.ymax) - (ofsy+G.v2d->mask.ymin));       //      Scaling
744 }
745
746 /* sets or clears hidden flags */
747 void check_action_context(SpaceAction *saction)
748 {
749         bActionChannel *achan;
750         
751         if (saction->action==NULL) return;
752         
753         for (achan=saction->action->chanbase.first; achan; achan=achan->next)
754                 achan->flag &= ~ACHAN_HIDDEN;
755         
756         if ((saction->pin==0) && ((saction->flag & SACTION_NOHIDE)==0) && (OBACT)) {
757                 Object *ob= OBACT;
758                 bPoseChannel *pchan;
759                 bArmature *arm= ob->data;
760                 
761                 for (achan=saction->action->chanbase.first; achan; achan=achan->next) {
762                         pchan= get_pose_channel(ob->pose, achan->name);
763                         if (pchan && pchan->bone) {
764                                 if ((pchan->bone->layer & arm->layer)==0)
765                                         achan->flag |= ACHAN_HIDDEN;
766                                 else if (pchan->bone->flag & BONE_HIDDEN_P)
767                                         achan->flag |= ACHAN_HIDDEN;
768                         }
769                 }
770         }
771 }
772
773 static void draw_channel_strips(void)
774 {
775         ListBase act_data = {NULL, NULL};
776         bActListElem *ale;
777         int filter;
778         void *data;
779         short datatype;
780         
781         rcti scr_rct;
782         gla2DDrawInfo *di;
783         float y, sta, end;
784         int act_start, act_end, dummy;
785         char col1[3], col2[3];
786         char col1a[3], col2a[3];
787         
788         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
789         BIF_GetThemeColor3ubv(TH_HILITE, col1);
790         BIF_GetThemeColor3ubv(TH_GROUP, col2a);
791         BIF_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
792
793         /* get editor data */
794         data= get_action_context(&datatype);
795         if (data == NULL) return;
796
797         scr_rct.xmin= G.saction->area->winrct.xmin + G.saction->v2d.mask.xmin;
798         scr_rct.ymin= G.saction->area->winrct.ymin + G.saction->v2d.mask.ymin;
799         scr_rct.xmax= G.saction->area->winrct.xmin + G.saction->v2d.hor.xmax;
800         scr_rct.ymax= G.saction->area->winrct.ymin + G.saction->v2d.mask.ymax; 
801         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
802
803         /* if in NLA there's a strip active, map the view */
804         if (datatype == ACTCONT_ACTION) {
805                 if (NLA_ACTION_SCALED)
806                         map_active_strip(di, OBACT, 0);
807                 
808                 /* start and end of action itself */
809                 calc_action_range(data, &sta, &end, 0);
810                 gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
811                 gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
812                 
813                 if (NLA_ACTION_SCALED)
814                         map_active_strip(di, OBACT, 1);
815         }
816         
817         /* build list of channels to draw */
818         filter= (ACTFILTER_FORDRAWING|ACTFILTER_VISIBLE|ACTFILTER_CHANNELS);
819         actdata_filter(&act_data, filter, data, datatype);
820         
821         /* first backdrop strips */
822         y = 0.0;
823         glEnable(GL_BLEND);
824         for (ale= act_data.first; ale; ale= ale->next) {
825                 int frame1_x, channel_y, sel=0;
826                 
827                 /* determine if any need to draw channel */
828                 if (ale->datatype != ALE_NONE) {
829                         /* determine if channel is selected */
830                         switch (ale->type) {
831                                 case ACTTYPE_GROUP:
832                                 {
833                                         bActionGroup *agrp = (bActionGroup *)ale->data;
834                                         sel = SEL_AGRP(agrp);
835                                 }
836                                         break;
837                                 case ACTTYPE_ACHAN:
838                                 {
839                                         bActionChannel *achan = (bActionChannel *)ale->data;
840                                         sel = SEL_ACHAN(achan);
841                                 }
842                                         break;
843                                 case ACTTYPE_CONCHAN:
844                                 {
845                                         bConstraintChannel *conchan = (bConstraintChannel *)ale->data;
846                                         sel = SEL_CONCHAN(conchan);
847                                 }
848                                         break;
849                                 case ACTTYPE_ICU:
850                                 {
851                                         IpoCurve *icu = (IpoCurve *)ale->data;
852                                         sel = SEL_ICU(icu);
853                                 }
854                                         break;
855                                 case ACTTYPE_GPLAYER:
856                                 {
857                                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
858                                         sel = SEL_GPL(gpl);
859                                 }
860                                         break;
861                         }
862                         
863                         if (datatype == ACTCONT_ACTION) {
864                                 gla2DDrawTranslatePt(di, G.v2d->cur.xmin, y, &frame1_x, &channel_y);
865                                 
866                                 if (ale->datatype == ALE_GROUP) {
867                                         if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
868                                         else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
869                                 }
870                                 else {
871                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
872                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
873                                 }
874                                 glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
875                                 
876                                 if (ale->datatype == ALE_GROUP) {
877                                         if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
878                                         else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
879                                 }
880                                 else {
881                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
882                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
883                                 }
884                                 glRectf(act_start,  channel_y-CHANNELHEIGHT/2,  act_end,  channel_y+CHANNELHEIGHT/2);
885                         }
886                         else if (datatype == ACTCONT_SHAPEKEY) {
887                                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
888                                 
889                                 /* all frames that have a frame number less than one
890                                  * get a desaturated orange background
891                                  */
892                                 glColor4ub(col2[0], col2[1], col2[2], 0x22);
893                                 glRectf(0, channel_y-CHANNELHEIGHT/2, frame1_x, channel_y+CHANNELHEIGHT/2);
894                                 
895                                 /* frames one and higher get a saturated orange background */
896                                 glColor4ub(col2[0], col2[1], col2[2], 0x44);
897                                 glRectf(frame1_x, channel_y-CHANNELHEIGHT/2, G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
898                         }
899                         else if (datatype == ACTCONT_GPENCIL) {
900                                 gla2DDrawTranslatePt(di, G.v2d->cur.xmin, y, &frame1_x, &channel_y);
901                                 
902                                 /* frames less than one get less saturated background */
903                                 if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
904                                 else glColor4ub(col2[0], col2[1], col2[2], 0x22);
905                                 glRectf(0, channel_y-CHANNELHEIGHT/2, frame1_x, channel_y+CHANNELHEIGHT/2);
906                                 
907                                 /* frames one and higher get a saturated background */
908                                 if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
909                                 else glColor4ub(col2[0], col2[1], col2[2], 0x44);
910                                 glRectf(frame1_x, channel_y-CHANNELHEIGHT/2, G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
911                         }
912                 }
913                 
914                 /*      Increment the step */
915                 y-=CHANNELHEIGHT+CHANNELSKIP;
916         }               
917         glDisable(GL_BLEND);
918         
919         if (NLA_ACTION_SCALED)
920                 map_active_strip(di, OBACT, 0);
921         
922         /* Draw keyframes 
923          *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
924          *         This is to try to optimise this for heavier data sets
925          *      2) Keyframes which are out of view horizontally are disregarded 
926          */
927         y = 0.0;
928         for (ale= act_data.first; ale; ale= ale->next) {
929                 const float yminc= y-CHANNELHEIGHT/2;
930                 const float ymaxc= y+CHANNELHEIGHT/2;
931                 
932                 /* check if visible */
933                 if ( IN_RANGE(yminc, G.v2d->cur.ymin, G.v2d->cur.ymax) ||
934                          IN_RANGE(ymaxc, G.v2d->cur.ymin, G.v2d->cur.ymax) ) 
935                 {
936                         switch (ale->datatype) {
937                                 case ALE_GROUP:
938                                         draw_agroup_channel(di, ale->data, y);
939                                         break;
940                                 case ALE_IPO:
941                                         draw_ipo_channel(di, ale->key_data, y);
942                                         break;
943                                 case ALE_ICU:
944                                         draw_icu_channel(di, ale->key_data, y);
945                                         break;
946                                 case ALE_GPFRAME:
947                                         draw_gpl_channel(di, ale->data, y);
948                                         break;
949                         }
950                 }
951                 
952                 y-=CHANNELHEIGHT+CHANNELSKIP;
953         }
954         
955         /* free tempolary channels used for drawing */
956         BLI_freelistN(&act_data);
957
958         /* black line marking 'current frame' for Time-Slide transform mode */
959         if (G.saction->flag & SACTION_MOVING) {
960                 int frame1_x, channel_y;
961                 
962                 gla2DDrawTranslatePt(di, G.saction->timeslide, 0, &frame1_x, &channel_y);
963                 cpack(0x0);
964                 
965                 glBegin(GL_LINES);
966                 glVertex2f(frame1_x, G.v2d->mask.ymin - 100);
967                 glVertex2f(frame1_x, G.v2d->mask.ymax);
968                 glEnd();
969         }
970         
971         glaEnd2DDraw(di);
972 }
973
974 /* ********* action panel *********** */
975
976
977 void do_actionbuts(unsigned short event)
978 {
979         switch(event) {
980                 /* general */
981         case REDRAWVIEW3D:
982                 allqueue(REDRAWVIEW3D, 0);
983                 break;
984         case B_REDR:
985                 allqueue(REDRAWACTION, 0);
986                 break;
987                 
988                 /* action-groups */
989         case B_ACTCUSTCOLORS:   /* only when of the color wells is edited */
990         {
991                 bActionGroup *agrp= get_active_actiongroup(G.saction->action);
992                 
993                 if (agrp)
994                         agrp->customCol= -1;
995                         
996                 allqueue(REDRAWACTION, 0);
997         }
998                 break;
999         case B_ACTCOLSSELECTOR: /* sync color set after using selector */
1000         {
1001                 bActionGroup *agrp= get_active_actiongroup(G.saction->action);
1002                 
1003                 if (agrp) 
1004                         actionbone_group_copycolors(agrp, 1);
1005                         
1006                 allqueue(REDRAWACTION, 0);
1007         }
1008                 break;
1009         case B_ACTGRP_SELALL: /* select all grouped channels */
1010         {
1011                 bAction *act= G.saction->action;
1012                 bActionGroup *agrp= get_active_actiongroup(act);
1013                 
1014                 /* select all in group, then reselect/activate group as the previous operation clears that */
1015                 select_action_group_channels(act, agrp);
1016                 agrp->flag |= (AGRP_ACTIVE|AGRP_SELECTED);
1017                 
1018                 allqueue(REDRAWACTION, 0);
1019         }
1020                 break;
1021         case B_ACTGRP_ADDTOSELF: /* add all selected action channels to self */
1022                 action_groups_group(0);
1023                 break;
1024         case B_ACTGRP_UNGROUP: /* remove channels from active group */
1025                 // FIXME: todo...
1026                 printf("FIXME: remove achans from active Action-Group not implemented yet! \n");
1027                 break;
1028         
1029         }
1030 }
1031
1032 // currently not used...
1033 static void action_panel_properties(short cntrl)        // ACTION_HANDLER_PROPERTIES
1034 {
1035         uiBlock *block;
1036         void *data;
1037         short datatype;
1038         
1039         block= uiNewBlock(&curarea->uiblocks, "action_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
1040         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
1041         uiSetPanelHandler(ACTION_HANDLER_PROPERTIES);  // for close and esc
1042         
1043         /* get datatype */
1044         data= get_action_context(&datatype);
1045         //if (data == NULL) return;
1046         
1047         if (uiNewPanel(curarea, block, "Active Channel Properties", "Action", 10, 230, 318, 204)==0) 
1048                 return;
1049         
1050         /* currently, only show data for actions */
1051         if (datatype == ACTCONT_ACTION) {
1052                 bActionGroup *agrp= get_active_actiongroup(data);
1053                 //bActionChannel *achan= get_hilighted_action_channel(data);
1054                 char *menustr;
1055                 
1056                 /* only for action-groups */
1057                 if (agrp) {
1058                         /* general stuff */
1059                         uiDefBut(block, LABEL, 1, "Action Group:",                                      10, 180, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
1060                         
1061                         uiDefBut(block, TEX, B_REDR, "Name: ",  10,160,150,20, agrp->name, 0.0, 31.0, 0, 0, "");
1062                         uiBlockBeginAlign(block);
1063                                 uiDefButBitI(block, TOG, AGRP_EXPANDED, B_REDR, "Expanded", 170, 160, 75, 20, &agrp->flag, 0, 0, 0, 0, "Action Group is expanded");
1064                                 uiDefButBitI(block, TOG, AGRP_PROTECTED, B_REDR, "Protected", 245, 160, 75, 20, &agrp->flag, 0, 0, 0, 0, "Action Group is protected");
1065                         uiBlockEndAlign(block);
1066                         
1067                         /* color stuff */
1068                         uiDefBut(block, LABEL, 1, "Group Colors:",      10, 107, 150, 19, NULL, 0.0, 0.0, 0, 0, "");
1069                         uiBlockBeginAlign(block);
1070                                 menustr= BIF_ThemeColorSetsPup(1);
1071                                 uiDefButI(block, MENU,B_ACTCOLSSELECTOR, menustr, 10,85,150,19, &agrp->customCol, -1, 20, 0.0, 0.0, "Index of set of Custom Colors to shade Group's bones with. 0 = Use Default Color Scheme, -1 = Use Custom Color Scheme");                                           
1072                                 MEM_freeN(menustr);
1073                                 
1074                                 /* show color-selection/preview */
1075                                 if (agrp->customCol) {
1076                                         /* do color copying/init (to stay up to date) */
1077                                         actionbone_group_copycolors(agrp, 1);
1078                                         
1079                                         /* color changing */
1080                                         uiDefButC(block, COL, B_ACTCUSTCOLORS, "",              10, 65, 50, 19, agrp->cs.active, 0, 0, 0, 0, "Color to use for 'top-level' channels");
1081                                         uiDefButC(block, COL, B_ACTCUSTCOLORS, "",              60, 65, 50, 19, agrp->cs.select, 0, 0, 0, 0, "Color to use for '2nd-level' channels");
1082                                         uiDefButC(block, COL, B_ACTCUSTCOLORS, "",              110, 65, 50, 19, agrp->cs.solid, 0, 0, 0, 0, "Color to use for '3rd-level' channels");
1083                                 }
1084                         uiBlockEndAlign(block);
1085                         
1086                         /* commands for active group */
1087                         uiDefBut(block, BUT, B_ACTGRP_SELALL, "Select Grouped", 170,85,150,20, 0, 21, 0, 0, 0, "Select all action-channels belonging to this group (same as doing Ctrl-Shift-LMB)");
1088                         
1089                         uiBlockBeginAlign(block);
1090                                 uiDefBut(block, BUT, B_ACTGRP_ADDTOSELF, "Add to Group",        170,60,150,20, 0, 21, 0, 0, 0, "Add selected action-channels to this group");
1091                                 uiDefBut(block, BUT, B_ACTGRP_UNGROUP, "Un-Group",      170,40,150,20, 0, 21, 0, 0, 0, "Remove selected action-channels from this group (unimplemented)");
1092                         uiBlockEndAlign(block);
1093                 }
1094         }
1095         else {
1096                 /* Currently, there isn't anything to display for these types ... */
1097         }
1098 }
1099
1100 static void action_blockhandlers(ScrArea *sa)
1101 {
1102         SpaceAction *sact= sa->spacedata.first;
1103         short a;
1104         
1105         for (a=0; a<SPACE_MAXHANDLER; a+=2) {
1106                 switch(sact->blockhandler[a]) {
1107                         case ACTION_HANDLER_PROPERTIES:
1108                                 action_panel_properties(sact->blockhandler[a+1]);
1109                                 break;
1110                 }
1111                 
1112                 /* clear action value for event */
1113                 sact->blockhandler[a+1]= 0;
1114         }
1115         
1116         uiDrawBlocksPanels(sa, 0);
1117 }
1118
1119 /* ************************* Action Editor Space ***************************** */
1120
1121 void drawactionspace(ScrArea *sa, void *spacedata)
1122 {
1123         bAction *act = NULL;
1124         Key *key = NULL;
1125         bGPdata *gpd = NULL;
1126         void *data;
1127         short datatype;
1128         
1129         short ofsx = 0, ofsy = 0;
1130         float col[3];
1131
1132         /* this is unlikely to occur, but it may */
1133         if (G.saction == NULL)
1134                 return;
1135
1136         /* warning: blocks need to be freed each time, handlers dont remove  */
1137         uiFreeBlocksWin(&sa->uiblocks, sa->win);
1138
1139         /* only try to refresh action that's displayed if not pinned */
1140         if (G.saction->pin==0) {
1141                 /* depends on mode */
1142                 switch (G.saction->mode) {
1143                         case SACTCONT_ACTION:
1144                         {
1145                                 if (OBACT)
1146                                         G.saction->action = OBACT->action;
1147                                 else
1148                                         G.saction->action= NULL;
1149                         }
1150                                 break;
1151                         case SACTCONT_GPENCIL:
1152                         {
1153                                 /* this searching could be slow (so users should pin after this is found) */
1154                                 G.saction->gpd= gpencil_data_getetime(G.curscreen);
1155                         }
1156                                 break;
1157                 }
1158         }
1159         
1160         /* get data */
1161         data = get_action_context(&datatype);
1162         switch (datatype) {
1163                 case ACTCONT_ACTION:
1164                         act = data;
1165                         break;
1166                 case ACTCONT_SHAPEKEY:
1167                         key = data;
1168                         break;
1169                 case ACTCONT_GPENCIL:
1170                         gpd = data;
1171                         break;
1172         }
1173         
1174         /* Lets make sure the width of the left hand of the screen
1175          * is set to an appropriate value based on whether sliders
1176          * are showing of not
1177          */
1178         if ((data) && (G.saction->flag & SACTION_SLIDERS)) 
1179                 ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
1180         else 
1181                 ACTWIDTH = NAMEWIDTH;
1182
1183         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1184
1185         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
1186
1187         /* background color for entire window (used in lefthand part though) */
1188         BIF_GetThemeColor3fv(TH_HEADER, col);
1189         glClearColor(col[0], col[1], col[2], 0.0); 
1190         glClear(GL_COLOR_BUFFER_BIT);
1191         
1192         if (curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
1193                 if(G.v2d->scroll) {     
1194                         ofsx= curarea->winrct.xmin;     
1195                         ofsy= curarea->winrct.ymin;
1196                         glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
1197                                            ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1198                                            ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
1199                         glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, 
1200                                           ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1201                                           ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
1202                 }
1203         }
1204
1205         BIF_GetThemeColor3fv(TH_BACK, col);
1206         glClearColor(col[0], col[1], col[2], 0.0);
1207         glClear(GL_COLOR_BUFFER_BIT);
1208
1209         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
1210         bwin_clear_viewmat(sa->win);    /* clear buttons view */
1211         glLoadIdentity();
1212
1213         /*      Draw backdrop */
1214         calc_ipogrid(); 
1215         draw_ipogrid();
1216
1217         check_action_context(G.saction);
1218         
1219         /* Draw channel strips */
1220         draw_channel_strips();
1221         
1222         /* reset matrices for stuff to be drawn on top of keys*/
1223         glViewport(ofsx+G.v2d->mask.xmin,  
1224              ofsy+G.v2d->mask.ymin, 
1225              ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1226              ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
1227         glScissor(ofsx+G.v2d->mask.xmin,  
1228             ofsy+G.v2d->mask.ymin, 
1229             ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, 
1230             ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
1231         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax,  G.v2d->cur.ymin, G.v2d->cur.ymax);
1232         
1233         /* Draw current frame */
1234         draw_cfra_action();
1235         
1236         /* Draw markers (local behind scene ones, as local obscure scene markers) */
1237         if (act) 
1238                 draw_markers_timespace(&act->markers, DRAW_MARKERS_LOCAL);
1239         draw_markers_timespace(SCE_MARKERS, 0);
1240         
1241         /* Draw 'curtains' for preview */
1242         draw_anim_preview_timespace();
1243
1244         /* Draw scroll */
1245         mywinset(curarea->win); // reset scissor too
1246         if (curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
1247                 myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1248                 if (G.v2d->scroll) drawscroll(0);
1249         }
1250
1251         /* Draw Left-Hand Panel if enough space in window */
1252         if (G.v2d->mask.xmin!=0) {
1253                 /* Draw channel names */
1254                 draw_channel_names();
1255                 
1256                 if(sa->winx > 50 + NAMEWIDTH + SLIDERWIDTH) {
1257                         if (act) {
1258                                 /* if there is an action, draw sliders for its
1259                                  * ipo-curve channels in the action window
1260                                  */
1261                                 action_icu_buts(G.saction);
1262                         }
1263                         else if (key) {
1264                                 /* if there is a mesh with rvk's selected,
1265                                  * then draw the key frames in the action window
1266                                  */
1267                                 meshactionbuts(G.saction, OBACT, key);
1268                         }
1269                 }
1270         }
1271         
1272         mywinset(curarea->win); // reset scissor too
1273         myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
1274         draw_area_emboss(sa);
1275
1276         /* it is important to end a view in a transform compatible with buttons */
1277         bwin_scalematrix(sa->win, G.saction->blockscale, G.saction->blockscale, G.saction->blockscale);
1278         action_blockhandlers(sa);
1279
1280         curarea->win_swap= WIN_BACK_OK;
1281 }
1282
1283 /* *************************** Keyframe Drawing *************************** */
1284
1285 static void add_bezt_to_keycolumnslist(ListBase *keys, BezTriple *bezt)
1286 {
1287         /* The equivilant of add_to_cfra_elem except this version 
1288          * makes ActKeyColumns - one of the two datatypes required
1289          * for action editor drawing.
1290          */
1291         ActKeyColumn *ak, *akn;
1292         
1293         if (ELEM(NULL, keys, bezt)) return;
1294         
1295         /* try to any existing key to replace, or where to insert after */
1296         for (ak= keys->last; ak; ak= ak->prev) {
1297                 /* do because of double keys */
1298                 if (ak->cfra == bezt->vec[1][0]) {                      
1299                         /* set selection status and 'touched' status */
1300                         if (BEZSELECTED(bezt)) ak->sel = SELECT;
1301                         ak->modified += 1;
1302                         
1303                         return;
1304                 }
1305                 else if (ak->cfra < bezt->vec[1][0]) break;
1306         }
1307         
1308         /* add new block */
1309         akn= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
1310         if (ak) BLI_insertlinkafter(keys, ak, akn);
1311         else BLI_addtail(keys, akn);
1312         
1313         akn->cfra= bezt->vec[1][0];
1314         akn->modified += 1;
1315         
1316         // TODO: handle type = bezt->h1 or bezt->h2
1317         akn->handle_type= 0; 
1318         
1319         if (BEZSELECTED(bezt))
1320                 akn->sel = SELECT;
1321         else
1322                 akn->sel = 0;
1323 }
1324
1325 static void add_bezt_to_keyblockslist(ListBase *blocks, IpoCurve *icu, int index)
1326 {
1327         /* The equivilant of add_to_cfra_elem except this version 
1328          * makes ActKeyBlocks - one of the two datatypes required
1329          * for action editor drawing.
1330          */
1331         ActKeyBlock *ab, *abn;
1332         BezTriple *beztn=NULL, *prev=NULL;
1333         BezTriple *bezt;
1334         int v;
1335         
1336         /* get beztriples */
1337         beztn= (icu->bezt + index);
1338         
1339         /* we need to go through all beztriples, as they may not be in order (i.e. during transform) */
1340         for (v=0, bezt=icu->bezt; v<icu->totvert; v++, bezt++) {
1341                 /* skip if beztriple is current */
1342                 if (v != index) {
1343                         /* check if beztriple is immediately before */
1344                         if (beztn->vec[1][0] > bezt->vec[1][0]) {
1345                                 /* check if closer than previous was */
1346                                 if (prev) {
1347                                         if (prev->vec[1][0] < bezt->vec[1][0])
1348                                                 prev= bezt;
1349                                 }
1350                                 else {
1351                                         prev= bezt;
1352                                 }
1353                         }
1354                 }
1355         }
1356         
1357         /* check if block needed - same value(s)?
1358          *      -> firstly, handles must have same central value as each other
1359          *      -> secondly, handles which control that section of the curve must be constant
1360          */
1361         if ((!prev) || (!beztn)) return;
1362         if (IS_EQ(beztn->vec[1][1], prev->vec[1][1])==0) return;
1363         if (IS_EQ(beztn->vec[1][1], beztn->vec[0][1])==0) return;
1364         if (IS_EQ(prev->vec[1][1], prev->vec[2][1])==0) return;
1365         
1366         /* try to find a keyblock that starts on the previous beztriple */
1367         for (ab= blocks->last; ab; ab= ab->prev) {
1368                 /* check if alter existing block or add new block */
1369                 if (ab->start == prev->vec[1][0]) {                     
1370                         /* set selection status and 'touched' status */
1371                         if (BEZSELECTED(beztn)) ab->sel = SELECT;
1372                         ab->modified += 1;
1373                         
1374                         return;
1375                 }
1376                 else if (ab->start < prev->vec[1][0]) break;
1377         }
1378         
1379         /* add new block */
1380         abn= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
1381         if (ab) BLI_insertlinkafter(blocks, ab, abn);
1382         else BLI_addtail(blocks, abn);
1383         
1384         abn->start= prev->vec[1][0];
1385         abn->end= beztn->vec[1][0];
1386         abn->val= beztn->vec[1][1];
1387         
1388         if (BEZSELECTED(prev) || BEZSELECTED(beztn))
1389                 abn->sel = SELECT;
1390         else
1391                 abn->sel = 0;
1392         abn->modified = 1;
1393 }
1394
1395 /* helper function - find actkeycolumn that occurs on cframe */
1396 static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe)
1397 {
1398         ActKeyColumn *ak, *ak2;
1399         
1400         if (keys==NULL) 
1401                 return NULL;
1402          
1403         /* search from both ends at the same time, and stop if we find match or if both ends meet */ 
1404         for (ak=keys->first, ak2=keys->last; ak && ak2; ak=ak->next, ak2=ak2->prev) {
1405                 /* return whichever end encounters the frame */
1406                 if (ak->cfra == cframe)
1407                         return ak;
1408                 if (ak2->cfra == cframe)
1409                         return ak2;
1410                 
1411                 /* no matches on either end, so return NULL */
1412                 if (ak == ak2)
1413                         return NULL;
1414         }
1415         
1416         return NULL;
1417 }
1418
1419 #if 0  // disabled, as some intel cards have problems with this
1420 /* Draw a simple diamond shape with a filled in center (in screen space) */
1421 static void draw_key_but(int x, int y, short w, short h, int sel)
1422 {
1423         int xmin= x, ymin= y;
1424         int xmax= x+w-1, ymax= y+h-1;
1425         int xc= (xmin+xmax)/2, yc= (ymin+ymax)/2;
1426         
1427         /* interior - hardcoded colors (for selected and unselected only) */
1428         if (sel) glColor3ub(0xF1, 0xCA, 0x13);
1429         else glColor3ub(0xE9, 0xE9, 0xE9);
1430         
1431         glBegin(GL_QUADS);
1432         glVertex2i(xc, ymin);
1433         glVertex2i(xmax, yc);
1434         glVertex2i(xc, ymax);
1435         glVertex2i(xmin, yc);
1436         glEnd();
1437         
1438         
1439         /* outline */
1440         glColor3ub(0, 0, 0);
1441         
1442         glBegin(GL_LINE_LOOP);
1443         glVertex2i(xc, ymin);
1444         glVertex2i(xmax, yc);
1445         glVertex2i(xc, ymax);
1446         glVertex2i(xmin, yc);
1447         glEnd();
1448 }
1449 #endif
1450
1451 static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos)
1452 {
1453         ActKeyColumn *ak;
1454         ActKeyBlock *ab;
1455         
1456         glEnable(GL_BLEND);
1457         
1458         /* draw keyblocks */
1459         if (blocks) {
1460                 for (ab= blocks->first; ab; ab= ab->next) {
1461                         short startCurves, endCurves, totCurves;
1462                         
1463                         /* find out how many curves occur at each keyframe */
1464                         ak= cfra_find_actkeycolumn(keys, ab->start);
1465                         startCurves = (ak)? ak->totcurve: 0;
1466                         
1467                         ak= cfra_find_actkeycolumn(keys, ab->end);
1468                         endCurves = (ak)? ak->totcurve: 0;
1469                         
1470                         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
1471                         if (!startCurves && !endCurves) 
1472                                 continue;
1473                         else
1474                                 totCurves = (startCurves>endCurves)? endCurves: startCurves;
1475                                 
1476                         if (ab->totcurve >= totCurves) {
1477                                 int sc_xa, sc_ya;
1478                                 int sc_xb, sc_yb;
1479                                 
1480                                 /* get co-ordinates of block */
1481                                 gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya);
1482                                 gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb);
1483                                 
1484                                 /* draw block */
1485                                 if (ab->sel)
1486                                         BIF_ThemeColor4(TH_STRIP_SELECT);
1487                                 else
1488                                         BIF_ThemeColor4(TH_STRIP);
1489                                 glRectf(sc_xa,  sc_ya-3,  sc_xb,  sc_yb+5);
1490                         }
1491                 }
1492         }
1493         
1494         /* draw keys */
1495         if (keys) {
1496                 for (ak= keys->first; ak; ak= ak->next) {
1497                         int sc_x, sc_y;
1498                         
1499                         /* get co-ordinate to draw at */
1500                         gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
1501                         
1502                         /* draw using icons - old way which is slower but more proven */
1503                         if(ak->sel & SELECT) BIF_icon_draw_aspect(sc_x-7, sc_y-6, ICON_SPACE2, 1.0f);
1504                         else BIF_icon_draw_aspect(sc_x-7, sc_y-6, ICON_SPACE3, 1.0f);
1505                         
1506                         /* draw using OpenGL - slightly uglier but faster */
1507                         //      NOTE: disabled for now, as some intel cards seem to have problems with this
1508                         //draw_key_but(sc_x-5, sc_y-4, 11, 11, (ak->sel & SELECT));
1509                 }       
1510         }
1511         
1512         glDisable(GL_BLEND);
1513 }
1514
1515
1516 static ActKeysInc *init_aki_data()
1517 {
1518         static ActKeysInc aki;
1519         
1520         /* init data of static struct here */
1521         if ((curarea->spacetype == SPACE_ACTION) && NLA_ACTION_SCALED &&
1522                 (G.saction->mode == SACTCONT_ACTION))
1523         {
1524                 aki.ob= OBACT;
1525         }
1526         else if (curarea->spacetype == SPACE_NLA)
1527         {
1528                 aki.ob= NULL; // FIXME
1529         }
1530         else
1531                 aki.ob= NULL;
1532                 
1533         aki.start= G.v2d->cur.xmin - 10;
1534         aki.end= G.v2d->cur.xmax + 10;
1535         
1536         /* only pass pointer for Action Editor if enabled (for now) */
1537         if ((curarea->spacetype == SPACE_ACTION) && (G.saction->flag & SACTION_HORIZOPTIMISEON))
1538                 return &aki;
1539         else    
1540                 return NULL;
1541 }
1542
1543 void draw_object_channel(gla2DDrawInfo *di, Object *ob, float ypos)
1544 {
1545         ListBase keys = {0, 0};
1546         ListBase blocks = {0, 0};
1547         ActKeysInc *aki = init_aki_data();
1548
1549         ob_to_keylist(ob, &keys, &blocks, aki);
1550         draw_keylist(di, &keys, &blocks, ypos);
1551         
1552         BLI_freelistN(&keys);
1553         BLI_freelistN(&blocks);
1554 }
1555
1556 void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, float ypos)
1557 {
1558         ListBase keys = {0, 0};
1559         ListBase blocks = {0, 0};
1560         ActKeysInc *aki = init_aki_data();
1561
1562         ipo_to_keylist(ipo, &keys, &blocks, aki);
1563         draw_keylist(di, &keys, &blocks, ypos);
1564         
1565         BLI_freelistN(&keys);
1566         BLI_freelistN(&blocks);
1567 }
1568
1569 void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, float ypos)
1570 {
1571         ListBase keys = {0, 0};
1572         ListBase blocks = {0, 0};
1573         ActKeysInc *aki = init_aki_data();
1574
1575         icu_to_keylist(icu, &keys, &blocks, aki);
1576         draw_keylist(di, &keys, &blocks, ypos);
1577         
1578         BLI_freelistN(&keys);
1579         BLI_freelistN(&blocks);
1580 }
1581
1582 void draw_agroup_channel(gla2DDrawInfo *di, bActionGroup *agrp, float ypos)
1583 {
1584         ListBase keys = {0, 0};
1585         ListBase blocks = {0, 0};
1586         ActKeysInc *aki = init_aki_data();
1587
1588         agroup_to_keylist(agrp, &keys, &blocks, aki);
1589         draw_keylist(di, &keys, &blocks, ypos);
1590         BLI_freelistN(&keys);
1591         BLI_freelistN(&blocks);
1592 }
1593
1594 void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos)
1595 {
1596         ListBase keys = {0, 0};
1597         ActKeysInc *aki = init_aki_data();
1598
1599         action_to_keylist(act, &keys, NULL, aki);
1600         draw_keylist(di, &keys, NULL, ypos);
1601         BLI_freelistN(&keys);
1602 }
1603
1604 void draw_gpl_channel(gla2DDrawInfo *di, bGPDlayer *gpl, float ypos)
1605 {
1606         ListBase keys = {0, 0};
1607         ActKeysInc *aki = init_aki_data();
1608         
1609         gpl_to_keylist(gpl, &keys, NULL, aki);
1610         draw_keylist(di, &keys, NULL, ypos);
1611         BLI_freelistN(&keys);
1612 }
1613
1614 /* --------------- Conversion: data -> keyframe list ------------------ */
1615
1616 void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
1617 {
1618         bConstraintChannel *conchan;
1619
1620         if (ob) {
1621                 /* Add object keyframes */
1622                 if (ob->ipo)
1623                         ipo_to_keylist(ob->ipo, keys, blocks, aki);
1624                 
1625                 /* Add constraint keyframes */
1626                 for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) {
1627                         if (conchan->ipo)
1628                                 ipo_to_keylist(conchan->ipo, keys, blocks, aki);                
1629                 }
1630                         
1631                 /* Add object data keyframes */
1632                 //              TODO??
1633         }
1634 }
1635
1636 static short bezt_in_aki_range (ActKeysInc *aki, BezTriple *bezt)
1637 {
1638         /* when aki == NULL, we don't care about range */
1639         if (aki == NULL) 
1640                 return 1;
1641                 
1642         /* if nla-scaling is in effect, apply appropriate scaling adjustments */
1643         if (aki->ob) {
1644                 float frame= get_action_frame_inv(aki->ob, bezt->vec[1][0]);
1645                 return IN_RANGE(frame, aki->start, aki->end);
1646         }
1647         else {
1648                 /* check if in range */
1649                 return IN_RANGE(bezt->vec[1][0], aki->start, aki->end);
1650         }
1651 }
1652
1653 void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
1654 {
1655         BezTriple *bezt;
1656         ActKeyColumn *ak, *ak2;
1657         ActKeyBlock *ab, *ab2;
1658         int v;
1659         
1660         if (icu && icu->totvert) {
1661                 /* loop through beztriples, making ActKeys and ActKeyBlocks */
1662                 bezt= icu->bezt;
1663                 
1664                 for (v=0; v<icu->totvert; v++, bezt++) {
1665                         /* only if keyframe is in range (optimisation) */
1666                         if (bezt_in_aki_range(aki, bezt)) {
1667                                 add_bezt_to_keycolumnslist(keys, bezt);
1668                                 if (blocks) add_bezt_to_keyblockslist(blocks, icu, v);
1669                         }
1670                 }
1671                 
1672                 /* update the number of curves that elements have appeared in  */
1673                 if (keys) {
1674                         for (ak=keys->first, ak2=keys->last; ak && ak2; ak=ak->next, ak2=ak2->prev) {
1675                                 if (ak->modified) {
1676                                         ak->modified = 0;
1677                                         ak->totcurve += 1;
1678                                 }
1679                                 if (ak2->modified) {
1680                                         ak2->modified = 0;
1681                                         ak2->totcurve += 1;
1682                                 }
1683                                 
1684                                 if (ak == ak2)
1685                                         break;
1686                         }
1687                 }
1688                 if (blocks) {
1689                         for (ab=blocks->first, ab2=blocks->last; ab && ab2; ab=ab->next, ab2=ab2->prev) {
1690                                 if (ab->modified) {
1691                                         ab->modified = 0;
1692                                         ab->totcurve += 1;
1693                                 }
1694                                 if (ab2->modified) {
1695                                         ab2->modified = 0;
1696                                         ab2->totcurve += 1;
1697                                 }
1698                                 
1699                                 if (ab == ab2)
1700                                         break;
1701                         }
1702                 }
1703         }
1704 }
1705
1706 void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
1707 {
1708         IpoCurve *icu;
1709         
1710         if (ipo) {
1711                 for (icu= ipo->curve.first; icu; icu= icu->next)
1712                         icu_to_keylist(icu, keys, blocks, aki);
1713         }
1714 }
1715
1716 void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
1717 {
1718         bActionChannel *achan;
1719         bConstraintChannel *conchan;
1720
1721         if (agrp) {
1722                 /* loop through action channels */
1723                 for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
1724                         if (VISIBLE_ACHAN(achan)) {
1725                                 /* firstly, add keys from action channel's ipo block */
1726                                 if (achan->ipo)
1727                                         ipo_to_keylist(achan->ipo, keys, blocks, aki);
1728                                 
1729                                 /* then, add keys from constraint channels */
1730                                 for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
1731                                         if (conchan->ipo)
1732                                                 ipo_to_keylist(conchan->ipo, keys, blocks, aki);
1733                                 }
1734                         }
1735                 }
1736         }
1737 }
1738
1739 void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
1740 {
1741         bActionChannel *achan;
1742         bConstraintChannel *conchan;
1743
1744         if (act) {
1745                 /* loop through action channels */
1746                 for (achan= act->chanbase.first; achan; achan= achan->next) {
1747                         /* firstly, add keys from action channel's ipo block */
1748                         if (achan->ipo)
1749                                 ipo_to_keylist(achan->ipo, keys, blocks, aki);
1750                         
1751                         /* then, add keys from constraint channels */
1752                         for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
1753                                 if (conchan->ipo)
1754                                         ipo_to_keylist(conchan->ipo, keys, blocks, aki);
1755                         }
1756                 }
1757         }
1758 }
1759
1760 void gpl_to_keylist(bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
1761 {
1762         bGPDframe *gpf;
1763         ActKeyColumn *ak;
1764         
1765         if (gpl && keys) {
1766                 /* loop over frames, converting directly to 'keyframes' (should be in order too) */
1767                 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
1768                         ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
1769                         BLI_addtail(keys, ak);
1770                         
1771                         ak->cfra= gpf->framenum;
1772                         ak->modified = 1;
1773                         ak->handle_type= 0; 
1774                         
1775                         if (gpf->flag & GP_FRAME_SELECT)
1776                                 ak->sel = SELECT;
1777                         else
1778                                 ak->sel = 0;
1779                 }
1780         }
1781 }
1782