Undo revision 23130 which was a merge with 2.5, a messy one because I did something...
[blender.git] / source / blender / editors / animation / keyframes_draw.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) 2009 Blender Foundation, Joshua Leung
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung (full recode)
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /* System includes ----------------------------------------------------- */
31
32 #include <math.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <float.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_arithb.h"
45 #include "BLI_dlrbTree.h"
46
47 #include "DNA_listBase.h"
48 #include "DNA_anim_types.h"
49 #include "DNA_action_types.h"
50 #include "DNA_armature_types.h"
51 #include "DNA_camera_types.h"
52 #include "DNA_curve_types.h"
53 #include "DNA_object_types.h"
54 #include "DNA_screen_types.h"
55 #include "DNA_scene_types.h"
56 #include "DNA_space_types.h"
57 #include "DNA_constraint_types.h"
58 #include "DNA_key_types.h"
59 #include "DNA_lamp_types.h"
60 #include "DNA_material_types.h"
61 #include "DNA_userdef_types.h"
62 #include "DNA_gpencil_types.h"
63 #include "DNA_windowmanager_types.h"
64 #include "DNA_world_types.h"
65 #include "DNA_view2d_types.h"
66
67 #include "BKE_action.h"
68 #include "BKE_depsgraph.h"
69 #include "BKE_fcurve.h"
70 #include "BKE_key.h"
71 #include "BKE_material.h"
72 #include "BKE_object.h"
73 #include "BKE_global.h"         // XXX remove me!
74 #include "BKE_context.h"
75 #include "BKE_utildefines.h"
76
77 #include "BIF_gl.h"
78 #include "BIF_glutil.h"
79
80 #include "UI_interface.h"
81 #include "UI_interface_icons.h"
82 #include "UI_resources.h"
83 #include "UI_view2d.h"
84
85 #include "ED_anim_api.h"
86 #include "ED_keyframing.h"
87 #include "ED_keyframes_draw.h"
88 #include "ED_screen.h"
89 #include "ED_space_api.h"
90
91 /* *************************** Keyframe Processing *************************** */
92
93 /* Create a ActKeyColumn from a BezTriple */
94 static ActKeyColumn *bezt_to_new_actkeycolumn(BezTriple *bezt)
95 {
96         ActKeyColumn *ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
97         
98         /* store settings based on state of BezTriple */
99         ak->cfra= bezt->vec[1][0];
100         ak->sel= BEZSELECTED(bezt) ? SELECT : 0;
101         
102         // TODO: handle type = bezt->h1 or bezt->h2
103         ak->handle_type= 0; 
104         
105         /* set 'modified', since this is used to identify long keyframes */
106         ak->modified = 1;
107         
108         return ak;
109 }
110
111 /* Add the given BezTriple to the given 'list' of Keyframes */
112 static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt)
113 {
114         ActKeyColumn *new_ak=NULL;
115         
116         if ELEM(NULL, keys, bezt) return;
117         
118         /* if there are no keys already, just add as root */
119         if (keys->root == NULL) {
120                 /* just add this as the root, then call the tree-balancing functions to validate */
121                 new_ak= bezt_to_new_actkeycolumn(bezt);
122                 keys->root= (DLRBT_Node *)new_ak;
123         }
124         else {
125                 ActKeyColumn *ak, *akp=NULL, *akn=NULL;
126                 
127                 /* traverse tree to find an existing entry to update the status of, 
128                  * or a suitable point to add at
129                  */
130                 for (ak= keys->root; ak; akp= ak, ak= akn) {
131                         /* check if this is a match, or whether we go left or right */
132                         if (ak->cfra == bezt->vec[1][0]) {
133                                 /* set selection status and 'touched' status */
134                                 if (BEZSELECTED(bezt)) ak->sel = SELECT;
135                                 ak->modified += 1;
136                                 
137                                 /* done... no need to insert */
138                                 return;
139                         }
140                         else {
141                                 ActKeyColumn **aknp= NULL; 
142                                 
143                                 /* check if go left or right, but if not available, add new node */
144                                 if (ak->cfra < bezt->vec[1][0]) 
145                                         aknp= &ak->right;
146                                 else
147                                         aknp= &ak->left;
148                                         
149                                 /* if this does not exist, add a new node, otherwise continue... */
150                                 if (*aknp == NULL) {
151                                         /* add a new node representing this, and attach it to the relevant place */
152                                         new_ak= bezt_to_new_actkeycolumn(bezt);
153                                         new_ak->parent= ak;
154                                         *aknp= new_ak;
155                                         break;
156                                 }
157                                 else
158                                         akn= *aknp;
159                         }
160                 }
161         }
162         
163         /* now, balance the tree taking into account this newly added node */
164         BLI_dlrbTree_insert(keys, (DLRBT_Node *)new_ak);
165 }
166
167
168 /* Create a ActKeyColumn for a pair of BezTriples */
169 static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
170 {
171         ActKeyBlock *ab= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
172         
173         ab->start= prev->vec[1][0];
174         ab->end= beztn->vec[1][0];
175         ab->val= beztn->vec[1][1];
176         
177         ab->sel= (BEZSELECTED(prev) || BEZSELECTED(beztn)) ? SELECT : 0;
178         ab->modified = 1;
179         
180         return ab;
181 }
182
183 static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, FCurve *fcu, int index)
184 {
185         ActKeyBlock *new_ab= NULL;
186         BezTriple *beztn=NULL, *prev=NULL;
187         BezTriple *bezt;
188         int v;
189         
190         /* get beztriples */
191         beztn= (fcu->bezt + index);
192         
193         /* we need to go through all beztriples, as they may not be in order (i.e. during transform) */
194         // TODO: this seems to be a bit of a bottleneck
195         for (v=0, bezt=fcu->bezt; v < fcu->totvert; v++, bezt++) {
196                 /* skip if beztriple is current */
197                 if (v != index) {
198                         /* check if beztriple is immediately before */
199                         if (beztn->vec[1][0] > bezt->vec[1][0]) {
200                                 /* check if closer than previous was */
201                                 if (prev) {
202                                         if (prev->vec[1][0] < bezt->vec[1][0])
203                                                 prev= bezt;
204                                 }
205                                 else {
206                                         prev= bezt;
207                                 }
208                         }
209                 }
210         }
211         
212         /* check if block needed - same value(s)?
213          *      -> firstly, handles must have same central value as each other
214          *      -> secondly, handles which control that section of the curve must be constant
215          */
216         if ((!prev) || (!beztn)) return;
217         if (IS_EQ(beztn->vec[1][1], prev->vec[1][1])==0) return;
218         if (IS_EQ(beztn->vec[1][1], beztn->vec[0][1])==0) return;
219         if (IS_EQ(prev->vec[1][1], prev->vec[2][1])==0) return;
220         
221         
222         /* if there are no blocks already, just add as root */
223         if (blocks->root == NULL) {
224                 /* just add this as the root, then call the tree-balancing functions to validate */
225                 new_ab= bezts_to_new_actkeyblock(prev, beztn);
226                 blocks->root= (DLRBT_Node *)new_ab;
227         }
228         else {
229                 ActKeyBlock *ab, *abp=NULL, *abn=NULL;
230                 
231                 /* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
232                  * Note: we can't search from end to try to optimise this as it causes errors there's
233                  *              an A ___ B |---| B situation
234                  */
235                 // FIXME: here there is a bug where we are trying to get the summary for the following channels
236                 //              A|--------------|A ______________ B|--------------|B
237                 //              A|------------------------------------------------|A
238                 //              A|----|A|---|A|-----------------------------------|A
239                 for (ab= blocks->root; ab; abp= ab, ab= abn) {
240                         /* check if this is a match, or whether we go left or right */
241                         if (ab->start == prev->vec[1][0]) {
242                                 /* set selection status and 'touched' status */
243                                 if (BEZSELECTED(beztn)) ab->sel = SELECT;
244                                 ab->modified += 1;
245                                 
246                                 /* done... no need to insert */
247                                 return;
248                         }
249                         else {
250                                 ActKeyBlock **abnp= NULL; 
251                                 
252                                 /* check if go left or right, but if not available, add new node */
253                                 if (ab->start < prev->vec[1][0]) 
254                                         abnp= &ab->right;
255                                 else
256                                         abnp= &ab->left;
257                                         
258                                 /* if this does not exist, add a new node, otherwise continue... */
259                                 if (*abnp == NULL) {
260                                         /* add a new node representing this, and attach it to the relevant place */
261                                         new_ab= bezts_to_new_actkeyblock(prev, beztn);
262                                         new_ab->parent= ab;
263                                         *abnp= new_ab;
264                                         break;
265                                 }
266                                 else
267                                         abn= *abnp;
268                         }
269                 }
270         }
271         
272         /* now, balance the tree taking into account this newly added node */
273         BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
274 }
275
276 /* --------- */
277
278 /* Handle the 'touched' status of ActKeyColumn tree nodes */
279 static void set_touched_actkeycolumn (ActKeyColumn *ak)
280 {
281         /* sanity check */
282         if (ak == NULL)
283                 return;
284                 
285         /* deal with self first */
286         if (ak->modified) {
287                 ak->modified= 0;
288                 ak->totcurve++;
289         }
290         
291         /* children */
292         set_touched_actkeycolumn(ak->left);
293         set_touched_actkeycolumn(ak->right);
294 }
295
296 /* Handle the 'touched' status of ActKeyBlock tree nodes */
297 static void set_touched_actkeyblock (ActKeyBlock *ab)
298 {
299         /* sanity check */
300         if (ab == NULL)
301                 return;
302                 
303         /* deal with self first */
304         if (ab->modified) {
305                 ab->modified= 0;
306                 ab->totcurve++;
307         }
308         
309         /* children */
310         set_touched_actkeyblock(ab->left);
311         set_touched_actkeyblock(ab->right);
312 }
313
314 /* *************************** Keyframe Drawing *************************** */
315
316 /* helper function - find actkeycolumn that occurs on cframe */
317 static ActKeyColumn *cfra_find_actkeycolumn (ActKeyColumn *ak, float cframe)
318 {
319         /* sanity checks */
320         if (ak == NULL)
321                 return NULL;
322         
323         /* check if this is a match, or whether it is in some subtree */
324         if (cframe < ak->cfra)
325                 return cfra_find_actkeycolumn(ak->left, cframe);
326         else if (cframe > ak->cfra)
327                 return cfra_find_actkeycolumn(ak->right, cframe);
328         else
329                 return ak; /* match */
330 }
331
332 /* -------- */
333
334 /* coordinates for diamond shape */
335 static const float _unit_diamond_shape[4][2] = {
336         {0.0f, 1.0f},   /* top vert */
337         {1.0f, 0.0f},   /* mid-right */
338         {0.0f, -1.0f},  /* bottom vert */
339         {-1.0f, 0.0f}   /* mid-left */
340 }; 
341
342 /* draw a simple diamond shape with OpenGL */
343 void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short mode)
344 {
345         static GLuint displist1=0;
346         static GLuint displist2=0;
347         
348         /* initialise 2 display lists for diamond shape - one empty, one filled */
349         if (displist1 == 0) {
350                 displist1= glGenLists(1);
351                         glNewList(displist1, GL_COMPILE);
352                         
353                         glBegin(GL_LINE_LOOP);
354                                 glVertex2fv(_unit_diamond_shape[0]);
355                                 glVertex2fv(_unit_diamond_shape[1]);
356                                 glVertex2fv(_unit_diamond_shape[2]);
357                                 glVertex2fv(_unit_diamond_shape[3]);
358                         glEnd();
359                 glEndList();
360         }
361         if (displist2 == 0) {
362                 displist2= glGenLists(1);
363                         glNewList(displist2, GL_COMPILE);
364                         
365                         glBegin(GL_QUADS);
366                                 glVertex2fv(_unit_diamond_shape[0]);
367                                 glVertex2fv(_unit_diamond_shape[1]);
368                                 glVertex2fv(_unit_diamond_shape[2]);
369                                 glVertex2fv(_unit_diamond_shape[3]);
370                         glEnd();
371                 glEndList();
372         }
373         
374         /* adjust view transform before starting */
375         glTranslatef(x, y, 0.0f);
376         glScalef(1.0f/xscale*hsize, hsize, 1.0f);
377         
378         /* anti-aliased lines for more consistent appearance */
379         glEnable(GL_LINE_SMOOTH);
380         
381         /* draw! */
382         if ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH) {
383                 /* interior - hardcoded colors (for selected and unselected only) */
384                 if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50);
385                 else glColor3ub(0xE9, 0xE9, 0xE9);
386                 
387                 glCallList(displist2);
388         }
389         
390         if ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH) {
391                 /* exterior - black frame */
392                 glColor3ub(0, 0, 0);
393                 
394                 glCallList(displist1);
395         }
396         
397         glDisable(GL_LINE_SMOOTH);
398         
399         /* restore view transform */
400         glScalef(xscale/hsize, 1.0f/hsize, 1.0);
401         glTranslatef(-x, -y, 0.0f);
402 }
403
404 static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos)
405 {
406         ActKeyColumn *ak;
407         ActKeyBlock *ab;
408         float xscale;
409         
410         glEnable(GL_BLEND);
411         
412         /* get View2D scaling factor */
413         UI_view2d_getscale(v2d, &xscale, NULL);
414         
415         /* draw keyblocks */
416         if (blocks) {
417                 for (ab= blocks->first; ab; ab= ab->next) {
418                         short startCurves, endCurves, totCurves;
419                         
420                         /* find out how many curves occur at each keyframe */
421                         ak= cfra_find_actkeycolumn((ActKeyColumn *)keys->root, ab->start);
422                         startCurves = (ak)? ak->totcurve: 0;
423                         
424                         ak= cfra_find_actkeycolumn((ActKeyColumn *)keys->root, ab->end);
425                         endCurves = (ak)? ak->totcurve: 0;
426                         
427                         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
428                         if (!startCurves && !endCurves) 
429                                 continue;
430                         else
431                                 totCurves = (startCurves>endCurves)? endCurves: startCurves;
432                                 
433                         if (ab->totcurve >= totCurves) {
434                                 /* draw block */
435                                 if (ab->sel)
436                                         UI_ThemeColor4(TH_STRIP_SELECT);
437                                 else
438                                         UI_ThemeColor4(TH_STRIP);
439                                 
440                                 glRectf(ab->start, ypos-5, ab->end, ypos+5);
441                         }
442                 }
443         }
444         
445         /* draw keys */
446         if (keys) {
447                 for (ak= keys->first; ak; ak= ak->next) {
448                         /* optimisation: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw 
449                          *      - this might give some improvements, since we current have to flip between view/region matrices
450                          */
451                         if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
452                                 continue;
453                         
454                         /* draw using OpenGL - uglier but faster */
455                         // NOTE1: a previous version of this didn't work nice for some intel cards
456                         // NOTE2: if we wanted to go back to icons, these are  icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3;
457                         draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), KEYFRAME_SHAPE_BOTH);
458                 }       
459         }
460         
461         glDisable(GL_BLEND);
462 }
463
464 /* *************************** Channel Drawing Funcs *************************** */
465
466 void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
467 {
468         DLRBT_Tree keys, blocks;
469         
470         BLI_dlrbTree_init(&keys);
471         BLI_dlrbTree_init(&blocks);
472         
473                 scene_to_keylist(ads, sce, &keys, &blocks);
474         
475         BLI_dlrbTree_linkedlist_sync(&keys);
476         BLI_dlrbTree_linkedlist_sync(&blocks);
477         
478                 draw_keylist(v2d, &keys, &blocks, ypos);
479         
480         BLI_dlrbTree_free(&keys);
481         BLI_dlrbTree_free(&blocks);
482 }
483
484 void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
485 {
486         DLRBT_Tree keys, blocks;
487         
488         BLI_dlrbTree_init(&keys);
489         BLI_dlrbTree_init(&blocks);
490         
491                 ob_to_keylist(ads, ob, &keys, &blocks);
492         
493         BLI_dlrbTree_linkedlist_sync(&keys);
494         BLI_dlrbTree_linkedlist_sync(&blocks);
495         
496                 draw_keylist(v2d, &keys, &blocks, ypos);
497         
498         BLI_dlrbTree_free(&keys);
499         BLI_dlrbTree_free(&blocks);
500 }
501
502 void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
503 {
504         DLRBT_Tree keys, blocks;
505         
506         BLI_dlrbTree_init(&keys);
507         BLI_dlrbTree_init(&blocks);
508         
509                 fcurve_to_keylist(adt, fcu, &keys, &blocks);
510         
511         BLI_dlrbTree_linkedlist_sync(&keys);
512         BLI_dlrbTree_linkedlist_sync(&blocks);
513         
514                 draw_keylist(v2d, &keys, &blocks, ypos);
515         
516         BLI_dlrbTree_free(&keys);
517         BLI_dlrbTree_free(&blocks);
518 }
519
520 void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
521 {
522         DLRBT_Tree keys, blocks;
523         
524         BLI_dlrbTree_init(&keys);
525         BLI_dlrbTree_init(&blocks);
526         
527                 agroup_to_keylist(adt, agrp, &keys, &blocks);
528         
529         BLI_dlrbTree_linkedlist_sync(&keys);
530         BLI_dlrbTree_linkedlist_sync(&blocks);
531         
532                 draw_keylist(v2d, &keys, &blocks, ypos);
533         
534         BLI_dlrbTree_free(&keys);
535         BLI_dlrbTree_free(&blocks);
536 }
537
538 void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
539 {
540         DLRBT_Tree keys, blocks;
541         
542         BLI_dlrbTree_init(&keys);
543         BLI_dlrbTree_init(&blocks);
544         
545                 action_to_keylist(adt, act, &keys, &blocks);
546         
547         BLI_dlrbTree_linkedlist_sync(&keys);
548         BLI_dlrbTree_linkedlist_sync(&blocks);
549         
550                 draw_keylist(v2d, &keys, &blocks, ypos);
551         
552         BLI_dlrbTree_free(&keys);
553         BLI_dlrbTree_free(&blocks);
554 }
555
556 void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
557 {
558         DLRBT_Tree keys;
559         
560         BLI_dlrbTree_init(&keys);
561         
562                 gpl_to_keylist(ads, gpl, &keys, NULL);
563         
564         BLI_dlrbTree_linkedlist_sync(&keys);
565         
566                 draw_keylist(v2d, &keys, NULL, ypos);
567         
568         BLI_dlrbTree_free(&keys);
569 }
570
571 /* *************************** Keyframe List Conversions *************************** */
572
573 void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree *blocks)
574 {
575         if (sce) {
576                 AnimData *adt;
577                 int filterflag;
578                 
579                 /* get filterflag */
580                 if (ads)
581                         filterflag= ads->filterflag;
582                 else
583                         filterflag= 0;
584                         
585                 /* scene animdata */
586                 if ((sce->adt) && !(filterflag & ADS_FILTER_NOSCE)) {
587                         adt= sce->adt;
588                         
589                         // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
590                         if (adt->action) 
591                                 action_to_keylist(adt, adt->action, keys, blocks);
592                 }
593                 
594                 /* world animdata */
595                 if ((sce->world) && (sce->world->adt) && !(filterflag & ADS_FILTER_NOWOR)) {
596                         adt= sce->world->adt;
597                         
598                         // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
599                         if (adt->action) 
600                                 action_to_keylist(adt, adt->action, keys, blocks);
601                 }
602         }
603 }
604
605 void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
606 {
607         Key *key= ob_get_key(ob);
608
609         if (ob) {
610                 int filterflag;
611                 
612                 /* get filterflag */
613                 if (ads)
614                         filterflag= ads->filterflag;
615                 else
616                         filterflag= 0;
617                 
618                 /* Add action keyframes */
619                 if (ob->adt && ob->adt->action)
620                         action_to_keylist(ob->adt, ob->adt->action, keys, blocks);
621                 
622                 /* Add shapekey keyframes (only if dopesheet allows, if it is available) */
623                 if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
624                         action_to_keylist(key->adt, key->adt->action, keys, blocks);
625                         
626                 // TODO: restore materials, and object data, etc.
627         }
628 }
629
630 void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
631 {
632         BezTriple *bezt;
633         int v;
634         
635         if (fcu && fcu->totvert && fcu->bezt) {
636                 /* apply NLA-mapping (if applicable) */
637                 if (adt)        
638                         ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1);
639                 
640                 /* loop through beztriples, making ActKeys and ActKeyBlocks */
641                 bezt= fcu->bezt;
642                 
643                 for (v=0; v < fcu->totvert; v++, bezt++) {
644                         add_bezt_to_keycolumns_list(keys, bezt);
645                         if (blocks) add_bezt_to_keyblocks_list(blocks, fcu, v);
646                 }
647                 
648                 /* update the number of curves that elements have appeared in  */
649                 // FIXME: this is broken with the new tree structure for now...
650                 if (keys)
651                         set_touched_actkeycolumn(keys->root);
652                 if (blocks)
653                         set_touched_actkeyblock(blocks->root);
654                 
655                 /* unapply NLA-mapping if applicable */
656                 ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1);
657         }
658 }
659
660 void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, DLRBT_Tree *blocks)
661 {
662         FCurve *fcu;
663
664         if (agrp) {
665                 /* loop through F-Curves */
666                 for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
667                         fcurve_to_keylist(adt, fcu, keys, blocks);
668                 }
669         }
670 }
671
672 void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree *blocks)
673 {
674         FCurve *fcu;
675
676         if (act) {
677                 /* loop through F-Curves */
678                 for (fcu= act->curves.first; fcu; fcu= fcu->next) {
679                         fcurve_to_keylist(adt, fcu, keys, blocks);
680                 }
681         }
682 }
683
684
685 void gpl_to_keylist(bDopeSheet *ads, bGPDlayer *gpl, DLRBT_Tree *keys, DLRBT_Tree *blocks)
686 {
687         bGPDframe *gpf;
688         ActKeyColumn *ak;
689         
690         if (gpl && keys) {
691                 /* loop over frames, converting directly to 'keyframes' (should be in order too) */
692                 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
693                         ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
694                         BLI_addtail((ListBase *)keys, ak);
695                         
696                         ak->cfra= (float)gpf->framenum;
697                         ak->modified = 1;
698                         ak->handle_type= 0; 
699                         
700                         if (gpf->flag & GP_FRAME_SELECT)
701                                 ak->sel = SELECT;
702                         else
703                                 ak->sel = 0;
704                 }
705         }
706 }
707