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