2.5 - Keyframes can now be marked as 'extremes' in addition to 'breakdowns'
[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         ak->key_type= BEZKEYTYPE(bezt); 
102         
103         /* set 'modified', since this is used to identify long keyframes */
104         ak->modified = 1;
105         
106         return ak;
107 }
108
109 /* Add the given BezTriple to the given 'list' of Keyframes */
110 static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt)
111 {
112         ActKeyColumn *new_ak=NULL;
113         
114         if ELEM(NULL, keys, bezt) return;
115         
116         /* if there are no keys already, just add as root */
117         if (keys->root == NULL) {
118                 /* just add this as the root, then call the tree-balancing functions to validate */
119                 new_ak= bezt_to_new_actkeycolumn(bezt);
120                 keys->root= (DLRBT_Node *)new_ak;
121         }
122         else {
123                 ActKeyColumn *ak, *akp=NULL, *akn=NULL;
124                 
125                 /* traverse tree to find an existing entry to update the status of, 
126                  * or a suitable point to add at
127                  */
128                 for (ak= keys->root; ak; akp= ak, ak= akn) {
129                         /* check if this is a match, or whether we go left or right */
130                         if (ak->cfra == bezt->vec[1][0]) {
131                                 /* set selection status and 'touched' status */
132                                 if (BEZSELECTED(bezt)) ak->sel = SELECT;
133                                 ak->modified += 1;
134                                 
135                                 /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
136                                 if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
137                                         ak->key_type= BEZT_KEYTYPE_KEYFRAME;
138                                 
139                                 /* done... no need to insert */
140                                 return;
141                         }
142                         else {
143                                 ActKeyColumn **aknp= NULL; 
144                                 
145                                 /* check if go left or right, but if not available, add new node */
146                                 if (ak->cfra < bezt->vec[1][0]) 
147                                         aknp= &ak->right;
148                                 else
149                                         aknp= &ak->left;
150                                         
151                                 /* if this does not exist, add a new node, otherwise continue... */
152                                 if (*aknp == NULL) {
153                                         /* add a new node representing this, and attach it to the relevant place */
154                                         new_ak= bezt_to_new_actkeycolumn(bezt);
155                                         new_ak->parent= ak;
156                                         *aknp= new_ak;
157                                         break;
158                                 }
159                                 else
160                                         akn= *aknp;
161                         }
162                 }
163         }
164         
165         /* now, balance the tree taking into account this newly added node */
166         BLI_dlrbTree_insert(keys, (DLRBT_Node *)new_ak);
167 }
168
169
170 /* Create a ActKeyColumn for a pair of BezTriples */
171 static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
172 {
173         ActKeyBlock *ab= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
174         
175         ab->start= prev->vec[1][0];
176         ab->end= beztn->vec[1][0];
177         ab->val= beztn->vec[1][1];
178         
179         ab->sel= (BEZSELECTED(prev) || BEZSELECTED(beztn)) ? SELECT : 0;
180         ab->modified = 1;
181         
182         return ab;
183 }
184
185 static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, FCurve *fcu, int index)
186 {
187         ActKeyBlock *new_ab= NULL;
188         BezTriple *beztn=NULL, *prev=NULL;
189         BezTriple *bezt;
190         int v;
191         
192         /* get beztriples */
193         beztn= (fcu->bezt + index);
194         
195         /* we need to go through all beztriples, as they may not be in order (i.e. during transform) */
196         // TODO: this seems to be a bit of a bottleneck
197         for (v=0, bezt=fcu->bezt; v < fcu->totvert; v++, bezt++) {
198                 /* skip if beztriple is current */
199                 if (v != index) {
200                         /* check if beztriple is immediately before */
201                         if (beztn->vec[1][0] > bezt->vec[1][0]) {
202                                 /* check if closer than previous was */
203                                 if (prev) {
204                                         if (prev->vec[1][0] < bezt->vec[1][0])
205                                                 prev= bezt;
206                                 }
207                                 else {
208                                         prev= bezt;
209                                 }
210                         }
211                 }
212         }
213         
214         /* check if block needed - same value(s)?
215          *      -> firstly, handles must have same central value as each other
216          *      -> secondly, handles which control that section of the curve must be constant
217          */
218         if ((!prev) || (!beztn)) return;
219         if (IS_EQ(beztn->vec[1][1], prev->vec[1][1])==0) return;
220         if (IS_EQ(beztn->vec[1][1], beztn->vec[0][1])==0) return;
221         if (IS_EQ(prev->vec[1][1], prev->vec[2][1])==0) return;
222         
223         
224         /* if there are no blocks already, just add as root */
225         if (blocks->root == NULL) {
226                 /* just add this as the root, then call the tree-balancing functions to validate */
227                 new_ab= bezts_to_new_actkeyblock(prev, beztn);
228                 blocks->root= (DLRBT_Node *)new_ab;
229         }
230         else {
231                 ActKeyBlock *ab, *abp=NULL, *abn=NULL;
232                 
233                 /* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
234                  * Note: we can't search from end to try to optimise this as it causes errors there's
235                  *              an A ___ B |---| B situation
236                  */
237                 // FIXME: here there is a bug where we are trying to get the summary for the following channels
238                 //              A|--------------|A ______________ B|--------------|B
239                 //              A|------------------------------------------------|A
240                 //              A|----|A|---|A|-----------------------------------|A
241                 for (ab= blocks->root; ab; abp= ab, ab= abn) {
242                         /* check if this is a match, or whether we go left or right */
243                         if (ab->start == prev->vec[1][0]) {
244                                 /* set selection status and 'touched' status */
245                                 if (BEZSELECTED(beztn)) ab->sel = SELECT;
246                                 ab->modified += 1;
247                                 
248                                 /* done... no need to insert */
249                                 return;
250                         }
251                         else {
252                                 ActKeyBlock **abnp= NULL; 
253                                 
254                                 /* check if go left or right, but if not available, add new node */
255                                 if (ab->start < prev->vec[1][0]) 
256                                         abnp= &ab->right;
257                                 else
258                                         abnp= &ab->left;
259                                         
260                                 /* if this does not exist, add a new node, otherwise continue... */
261                                 if (*abnp == NULL) {
262                                         /* add a new node representing this, and attach it to the relevant place */
263                                         new_ab= bezts_to_new_actkeyblock(prev, beztn);
264                                         new_ab->parent= ab;
265                                         *abnp= new_ab;
266                                         break;
267                                 }
268                                 else
269                                         abn= *abnp;
270                         }
271                 }
272         }
273         
274         /* now, balance the tree taking into account this newly added node */
275         BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
276 }
277
278 /* --------- */
279
280 /* Handle the 'touched' status of ActKeyColumn tree nodes */
281 static void set_touched_actkeycolumn (ActKeyColumn *ak)
282 {
283         /* sanity check */
284         if (ak == NULL)
285                 return;
286                 
287         /* deal with self first */
288         if (ak->modified) {
289                 ak->modified= 0;
290                 ak->totcurve++;
291         }
292         
293         /* children */
294         set_touched_actkeycolumn(ak->left);
295         set_touched_actkeycolumn(ak->right);
296 }
297
298 /* Handle the 'touched' status of ActKeyBlock tree nodes */
299 static void set_touched_actkeyblock (ActKeyBlock *ab)
300 {
301         /* sanity check */
302         if (ab == NULL)
303                 return;
304                 
305         /* deal with self first */
306         if (ab->modified) {
307                 ab->modified= 0;
308                 ab->totcurve++;
309         }
310         
311         /* children */
312         set_touched_actkeyblock(ab->left);
313         set_touched_actkeyblock(ab->right);
314 }
315
316 /* *************************** Keyframe Drawing *************************** */
317
318 /* helper function - find actkeycolumn that occurs on cframe */
319 ActKeyColumn *cfra_find_actkeycolumn (ActKeyColumn *ak, float cframe)
320 {
321         /* sanity checks */
322         if (ak == NULL)
323                 return NULL;
324         
325         /* check if this is a match, or whether it is in some subtree */
326         if (cframe < ak->cfra)
327                 return cfra_find_actkeycolumn(ak->left, cframe);
328         else if (cframe > ak->cfra)
329                 return cfra_find_actkeycolumn(ak->right, cframe);
330         else
331                 return ak; /* match */
332 }
333
334 /* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */
335 // FIXME: this is buggy... next() is ignored completely...
336 ActKeyColumn *cfra_find_nearest_next_ak (ActKeyColumn *ak, float cframe, short next)
337 {
338         ActKeyColumn *akn= NULL;
339         
340         /* sanity checks */
341         if (ak == NULL)
342                 return NULL;
343         
344         /* check if this is a match, or whether it is in some subtree */
345         if (cframe < ak->cfra)
346                 akn= cfra_find_nearest_next_ak(ak->left, cframe, next);
347         else if (cframe > ak->cfra)
348                 akn= cfra_find_nearest_next_ak(ak->right, cframe, next);
349                 
350         /* if no match found (or found match), just use the current one */
351         if (akn == NULL)
352                 return ak;
353         else
354                 return akn;
355 }
356
357 /* -------- */
358
359 /* coordinates for diamond shape */
360 static const float _unit_diamond_shape[4][2] = {
361         {0.0f, 1.0f},   /* top vert */
362         {1.0f, 0.0f},   /* mid-right */
363         {0.0f, -1.0f},  /* bottom vert */
364         {-1.0f, 0.0f}   /* mid-left */
365 }; 
366
367 /* draw a simple diamond shape with OpenGL */
368 void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short key_type, short mode)
369 {
370         static GLuint displist1=0;
371         static GLuint displist2=0;
372         
373         /* initialise 2 display lists for diamond shape - one empty, one filled */
374         if (displist1 == 0) {
375                 displist1= glGenLists(1);
376                         glNewList(displist1, GL_COMPILE);
377                         
378                         glBegin(GL_LINE_LOOP);
379                                 glVertex2fv(_unit_diamond_shape[0]);
380                                 glVertex2fv(_unit_diamond_shape[1]);
381                                 glVertex2fv(_unit_diamond_shape[2]);
382                                 glVertex2fv(_unit_diamond_shape[3]);
383                         glEnd();
384                 glEndList();
385         }
386         if (displist2 == 0) {
387                 displist2= glGenLists(1);
388                         glNewList(displist2, GL_COMPILE);
389                         
390                         glBegin(GL_QUADS);
391                                 glVertex2fv(_unit_diamond_shape[0]);
392                                 glVertex2fv(_unit_diamond_shape[1]);
393                                 glVertex2fv(_unit_diamond_shape[2]);
394                                 glVertex2fv(_unit_diamond_shape[3]);
395                         glEnd();
396                 glEndList();
397         }
398         
399         /* tweak size of keyframe shape according to type of keyframe 
400          *      - 'proper' keyframes have key_type=0, so get drawn at full size
401          */
402         hsize -= 0.5f*key_type;
403         
404         /* adjust view transform before starting */
405         glTranslatef(x, y, 0.0f);
406         glScalef(1.0f/xscale*hsize, hsize, 1.0f);
407         
408         /* anti-aliased lines for more consistent appearance */
409         glEnable(GL_LINE_SMOOTH);
410         
411         /* draw! */
412         if ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH) {
413                 /* interior - hardcoded colors (for selected and unselected only) */
414                 switch (key_type) {
415                         case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames for now */
416                         {
417                                 if (sel) glColor3f(0.33f, 0.75f, 0.93f);
418                                 else glColor3f(0.70f, 0.86f, 0.91f);
419                         }
420                                 break;
421                                 
422                         case BEZT_KEYTYPE_EXTREME: /* redish frames for now */
423                         {
424                                 if (sel) glColor3f(95.0f, 0.5f, 0.5f);
425                                 else glColor3f(0.91f, 0.70f, 0.80f);
426                         }
427                                 break;
428                                 
429                         case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames for now */
430                         default:
431                         {
432                                 if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50);
433                                 else glColor3f(0.91f, 0.91f, 0.91f);
434                         }
435                                 break;
436                 }
437                 
438                 glCallList(displist2);
439         }
440         
441         if ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH) {
442                 /* exterior - black frame */
443                 glColor3ub(0, 0, 0);
444                 
445                 glCallList(displist1);
446         }
447         
448         glDisable(GL_LINE_SMOOTH);
449         
450         /* restore view transform */
451         glScalef(xscale/hsize, 1.0f/hsize, 1.0);
452         glTranslatef(-x, -y, 0.0f);
453 }
454
455 static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos)
456 {
457         ActKeyColumn *ak;
458         ActKeyBlock *ab;
459         float xscale;
460         
461         glEnable(GL_BLEND);
462         
463         /* get View2D scaling factor */
464         UI_view2d_getscale(v2d, &xscale, NULL);
465         
466         /* draw keyblocks */
467         if (blocks) {
468                 for (ab= blocks->first; ab; ab= ab->next) {
469                         short startCurves, endCurves, totCurves;
470                         
471                         /* find out how many curves occur at each keyframe */
472                         ak= cfra_find_actkeycolumn((ActKeyColumn *)keys->root, ab->start);
473                         startCurves = (ak)? ak->totcurve: 0;
474                         
475                         ak= cfra_find_actkeycolumn((ActKeyColumn *)keys->root, ab->end);
476                         endCurves = (ak)? ak->totcurve: 0;
477                         
478                         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
479                         if (!startCurves && !endCurves) 
480                                 continue;
481                         else
482                                 totCurves = (startCurves>endCurves)? endCurves: startCurves;
483                                 
484                         if (ab->totcurve >= totCurves) {
485                                 /* draw block */
486                                 if (ab->sel)
487                                         UI_ThemeColor4(TH_STRIP_SELECT);
488                                 else
489                                         UI_ThemeColor4(TH_STRIP);
490                                 
491                                 glRectf(ab->start, ypos-5, ab->end, ypos+5);
492                         }
493                 }
494         }
495         
496         /* draw keys */
497         if (keys) {
498                 for (ak= keys->first; ak; ak= ak->next) {
499                         /* optimisation: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw 
500                          *      - this might give some improvements, since we current have to flip between view/region matrices
501                          */
502                         if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
503                                 continue;
504                         
505                         /* draw using OpenGL - uglier but faster */
506                         // NOTE1: a previous version of this didn't work nice for some intel cards
507                         // NOTE2: if we wanted to go back to icons, these are  icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3;
508                         draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH);
509                 }       
510         }
511         
512         glDisable(GL_BLEND);
513 }
514
515 /* *************************** Channel Drawing Funcs *************************** */
516
517 void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
518 {
519         DLRBT_Tree keys, blocks;
520         
521         BLI_dlrbTree_init(&keys);
522         BLI_dlrbTree_init(&blocks);
523         
524                 scene_to_keylist(ads, sce, &keys, &blocks);
525         
526         BLI_dlrbTree_linkedlist_sync(&keys);
527         BLI_dlrbTree_linkedlist_sync(&blocks);
528         
529                 draw_keylist(v2d, &keys, &blocks, ypos);
530         
531         BLI_dlrbTree_free(&keys);
532         BLI_dlrbTree_free(&blocks);
533 }
534
535 void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
536 {
537         DLRBT_Tree keys, blocks;
538         
539         BLI_dlrbTree_init(&keys);
540         BLI_dlrbTree_init(&blocks);
541         
542                 ob_to_keylist(ads, ob, &keys, &blocks);
543         
544         BLI_dlrbTree_linkedlist_sync(&keys);
545         BLI_dlrbTree_linkedlist_sync(&blocks);
546         
547                 draw_keylist(v2d, &keys, &blocks, ypos);
548         
549         BLI_dlrbTree_free(&keys);
550         BLI_dlrbTree_free(&blocks);
551 }
552
553 void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
554 {
555         DLRBT_Tree keys, blocks;
556         
557         BLI_dlrbTree_init(&keys);
558         BLI_dlrbTree_init(&blocks);
559         
560                 fcurve_to_keylist(adt, fcu, &keys, &blocks);
561         
562         BLI_dlrbTree_linkedlist_sync(&keys);
563         BLI_dlrbTree_linkedlist_sync(&blocks);
564         
565                 draw_keylist(v2d, &keys, &blocks, ypos);
566         
567         BLI_dlrbTree_free(&keys);
568         BLI_dlrbTree_free(&blocks);
569 }
570
571 void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
572 {
573         DLRBT_Tree keys, blocks;
574         
575         BLI_dlrbTree_init(&keys);
576         BLI_dlrbTree_init(&blocks);
577         
578                 agroup_to_keylist(adt, agrp, &keys, &blocks);
579         
580         BLI_dlrbTree_linkedlist_sync(&keys);
581         BLI_dlrbTree_linkedlist_sync(&blocks);
582         
583                 draw_keylist(v2d, &keys, &blocks, ypos);
584         
585         BLI_dlrbTree_free(&keys);
586         BLI_dlrbTree_free(&blocks);
587 }
588
589 void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
590 {
591         DLRBT_Tree keys, blocks;
592         
593         BLI_dlrbTree_init(&keys);
594         BLI_dlrbTree_init(&blocks);
595         
596                 action_to_keylist(adt, act, &keys, &blocks);
597         
598         BLI_dlrbTree_linkedlist_sync(&keys);
599         BLI_dlrbTree_linkedlist_sync(&blocks);
600         
601                 draw_keylist(v2d, &keys, &blocks, ypos);
602         
603         BLI_dlrbTree_free(&keys);
604         BLI_dlrbTree_free(&blocks);
605 }
606
607 void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
608 {
609         DLRBT_Tree keys;
610         
611         BLI_dlrbTree_init(&keys);
612         
613                 gpl_to_keylist(ads, gpl, &keys, NULL);
614         
615         BLI_dlrbTree_linkedlist_sync(&keys);
616         
617                 draw_keylist(v2d, &keys, NULL, ypos);
618         
619         BLI_dlrbTree_free(&keys);
620 }
621
622 /* *************************** Keyframe List Conversions *************************** */
623
624 void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree *blocks)
625 {
626         if (sce) {
627                 AnimData *adt;
628                 int filterflag;
629                 
630                 /* get filterflag */
631                 if (ads)
632                         filterflag= ads->filterflag;
633                 else
634                         filterflag= 0;
635                         
636                 /* scene animdata */
637                 if ((sce->adt) && !(filterflag & ADS_FILTER_NOSCE)) {
638                         adt= sce->adt;
639                         
640                         // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
641                         if (adt->action) 
642                                 action_to_keylist(adt, adt->action, keys, blocks);
643                 }
644                 
645                 /* world animdata */
646                 if ((sce->world) && (sce->world->adt) && !(filterflag & ADS_FILTER_NOWOR)) {
647                         adt= sce->world->adt;
648                         
649                         // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
650                         if (adt->action) 
651                                 action_to_keylist(adt, adt->action, keys, blocks);
652                 }
653         }
654 }
655
656 void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
657 {
658         Key *key= ob_get_key(ob);
659
660         if (ob) {
661                 int filterflag;
662                 
663                 /* get filterflag */
664                 if (ads)
665                         filterflag= ads->filterflag;
666                 else
667                         filterflag= 0;
668                 
669                 /* Add action keyframes */
670                 if (ob->adt && ob->adt->action)
671                         action_to_keylist(ob->adt, ob->adt->action, keys, blocks);
672                 
673                 /* Add shapekey keyframes (only if dopesheet allows, if it is available) */
674                 if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
675                         action_to_keylist(key->adt, key->adt->action, keys, blocks);
676                         
677                 // TODO: restore materials, and object data, etc.
678         }
679 }
680
681 void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
682 {
683         BezTriple *bezt;
684         int v;
685         
686         if (fcu && fcu->totvert && fcu->bezt) {
687                 /* apply NLA-mapping (if applicable) */
688                 if (adt)        
689                         ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1);
690                 
691                 /* loop through beztriples, making ActKeys and ActKeyBlocks */
692                 bezt= fcu->bezt;
693                 
694                 for (v=0; v < fcu->totvert; v++, bezt++) {
695                         add_bezt_to_keycolumns_list(keys, bezt);
696                         if (blocks) add_bezt_to_keyblocks_list(blocks, fcu, v);
697                 }
698                 
699                 /* update the number of curves that elements have appeared in  */
700                 // FIXME: this is broken with the new tree structure for now...
701                 if (keys)
702                         set_touched_actkeycolumn(keys->root);
703                 if (blocks)
704                         set_touched_actkeyblock(blocks->root);
705                 
706                 /* unapply NLA-mapping if applicable */
707                 ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1);
708         }
709 }
710
711 void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, DLRBT_Tree *blocks)
712 {
713         FCurve *fcu;
714
715         if (agrp) {
716                 /* loop through F-Curves */
717                 for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
718                         fcurve_to_keylist(adt, fcu, keys, blocks);
719                 }
720         }
721 }
722
723 void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree *blocks)
724 {
725         FCurve *fcu;
726
727         if (act) {
728                 /* loop through F-Curves */
729                 for (fcu= act->curves.first; fcu; fcu= fcu->next) {
730                         fcurve_to_keylist(adt, fcu, keys, blocks);
731                 }
732         }
733 }
734
735
736 void gpl_to_keylist(bDopeSheet *ads, bGPDlayer *gpl, DLRBT_Tree *keys, DLRBT_Tree *blocks)
737 {
738         bGPDframe *gpf;
739         ActKeyColumn *ak;
740         
741         if (gpl && keys) {
742                 /* loop over frames, converting directly to 'keyframes' (should be in order too) */
743                 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
744                         ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
745                         BLI_addtail((ListBase *)keys, ak);
746                         
747                         ak->cfra= (float)gpf->framenum;
748                         ak->modified = 1;
749                         ak->key_type= 0; 
750                         
751                         if (gpf->flag & GP_FRAME_SELECT)
752                                 ak->sel = SELECT;
753                         else
754                                 ak->sel = 0;
755                 }
756         }
757 }
758