2.5 - Action Editor: IPO Curve Protect works now
[blender.git] / source / blender / editors / animation / keyframes_draw.c
1 /**
2  * $Id: drawaction.c 17746 2008-12-08 11:19:44Z aligorith $
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  */
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
46 /* Types --------------------------------------------------------------- */
47
48 #include "DNA_listBase.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_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_lamp_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_userdef_types.h"
63 #include "DNA_gpencil_types.h"
64 #include "DNA_windowmanager_types.h"
65
66 #include "BKE_action.h"
67 #include "BKE_depsgraph.h"
68 #include "BKE_ipo.h"
69 #include "BKE_key.h"
70 #include "BKE_material.h"
71 #include "BKE_object.h"
72 #include "BKE_global.h"         // XXX remove me!
73 #include "BKE_context.h"
74 #include "BKE_utildefines.h"
75
76 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
77
78 #include "BIF_gl.h"
79 #include "BIF_glutil.h"
80
81 #include "UI_interface.h"
82 #include "UI_interface_icons.h"
83 #include "UI_resources.h"
84 #include "UI_text.h"
85 #include "UI_view2d.h"
86
87 #include "ED_anim_api.h"
88 #include "ED_keyframing.h"
89 #include "ED_keyframes_draw.h"
90 #include "ED_screen.h"
91 #include "ED_space_api.h"
92
93
94 #if 0 // XXX old includes for reference only
95         #include "BIF_editaction.h"
96         #include "BIF_editkey.h"
97         #include "BIF_editnla.h"
98         #include "BIF_drawgpencil.h"
99         #include "BIF_keyframing.h"
100         #include "BIF_language.h"
101         #include "BIF_space.h"
102         
103         #include "BDR_editcurve.h"
104         #include "BDR_gpencil.h"
105
106         #include "BSE_drawnla.h"
107         #include "BSE_drawipo.h"
108         #include "BSE_drawview.h"
109         #include "BSE_editaction_types.h"
110         #include "BSE_editipo.h"
111         #include "BSE_headerbuttons.h"
112         #include "BSE_time.h"
113         #include "BSE_view.h"
114 #endif // XXX old defines for reference only
115
116 /* *************************** Keyframe Drawing *************************** */
117
118 static void add_bezt_to_keycolumnslist(ListBase *keys, BezTriple *bezt)
119 {
120         /* The equivilant of add_to_cfra_elem except this version 
121          * makes ActKeyColumns - one of the two datatypes required
122          * for action editor drawing.
123          */
124         ActKeyColumn *ak, *akn;
125         
126         if (ELEM(NULL, keys, bezt)) return;
127         
128         /* try to any existing key to replace, or where to insert after */
129         for (ak= keys->last; ak; ak= ak->prev) {
130                 /* do because of double keys */
131                 if (ak->cfra == bezt->vec[1][0]) {                      
132                         /* set selection status and 'touched' status */
133                         if (BEZSELECTED(bezt)) ak->sel = SELECT;
134                         ak->modified += 1;
135                         
136                         return;
137                 }
138                 else if (ak->cfra < bezt->vec[1][0]) break;
139         }
140         
141         /* add new block */
142         akn= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
143         if (ak) BLI_insertlinkafter(keys, ak, akn);
144         else BLI_addtail(keys, akn);
145         
146         akn->cfra= bezt->vec[1][0];
147         akn->modified += 1;
148         
149         // TODO: handle type = bezt->h1 or bezt->h2
150         akn->handle_type= 0; 
151         
152         if (BEZSELECTED(bezt))
153                 akn->sel = SELECT;
154         else
155                 akn->sel = 0;
156 }
157
158 static void add_bezt_to_keyblockslist(ListBase *blocks, IpoCurve *icu, int index)
159 {
160         /* The equivilant of add_to_cfra_elem except this version 
161          * makes ActKeyBlocks - one of the two datatypes required
162          * for action editor drawing.
163          */
164         ActKeyBlock *ab, *abn;
165         BezTriple *beztn=NULL, *prev=NULL;
166         BezTriple *bezt;
167         int v;
168         
169         /* get beztriples */
170         beztn= (icu->bezt + index);
171         
172         /* we need to go through all beztriples, as they may not be in order (i.e. during transform) */
173         for (v=0, bezt=icu->bezt; v<icu->totvert; v++, bezt++) {
174                 /* skip if beztriple is current */
175                 if (v != index) {
176                         /* check if beztriple is immediately before */
177                         if (beztn->vec[1][0] > bezt->vec[1][0]) {
178                                 /* check if closer than previous was */
179                                 if (prev) {
180                                         if (prev->vec[1][0] < bezt->vec[1][0])
181                                                 prev= bezt;
182                                 }
183                                 else {
184                                         prev= bezt;
185                                 }
186                         }
187                 }
188         }
189         
190         /* check if block needed - same value(s)?
191          *      -> firstly, handles must have same central value as each other
192          *      -> secondly, handles which control that section of the curve must be constant
193          */
194         if ((!prev) || (!beztn)) return;
195         if (IS_EQ(beztn->vec[1][1], prev->vec[1][1])==0) return;
196         if (IS_EQ(beztn->vec[1][1], beztn->vec[0][1])==0) return;
197         if (IS_EQ(prev->vec[1][1], prev->vec[2][1])==0) return;
198         
199         /* try to find a keyblock that starts on the previous beztriple 
200          * Note: we can't search from end to try to optimise this as it causes errors there's
201          *              an A ___ B |---| B situation
202          */
203         // FIXME: here there is a bug where we are trying to get the summary for the following channels
204         //              A|--------------|A ______________ B|--------------|B
205         //              A|------------------------------------------------|A
206         //              A|----|A|---|A|-----------------------------------|A
207         for (ab= blocks->first; ab; ab= ab->next) {
208                 /* check if alter existing block or add new block */
209                 if (ab->start == prev->vec[1][0]) {                     
210                         /* set selection status and 'touched' status */
211                         if (BEZSELECTED(beztn)) ab->sel = SELECT;
212                         ab->modified += 1;
213                         
214                         return;
215                 }
216                 else if (ab->start < prev->vec[1][0]) break;
217         }
218         
219         /* add new block */
220         abn= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
221         if (ab) BLI_insertlinkbefore(blocks, ab, abn);
222         else BLI_addtail(blocks, abn);
223         
224         abn->start= prev->vec[1][0];
225         abn->end= beztn->vec[1][0];
226         abn->val= beztn->vec[1][1];
227         
228         if (BEZSELECTED(prev) || BEZSELECTED(beztn))
229                 abn->sel = SELECT;
230         else
231                 abn->sel = 0;
232         abn->modified = 1;
233 }
234
235 /* helper function - find actkeycolumn that occurs on cframe */
236 static ActKeyColumn *cfra_find_actkeycolumn (ListBase *keys, float cframe)
237 {
238         ActKeyColumn *ak, *ak2;
239         
240         if (keys==NULL) 
241                 return NULL;
242          
243         /* search from both ends at the same time, and stop if we find match or if both ends meet */ 
244         for (ak=keys->first, ak2=keys->last; ak && ak2; ak=ak->next, ak2=ak2->prev) {
245                 /* return whichever end encounters the frame */
246                 if (ak->cfra == cframe)
247                         return ak;
248                 if (ak2->cfra == cframe)
249                         return ak2;
250                 
251                 /* no matches on either end, so return NULL */
252                 if (ak == ak2)
253                         return NULL;
254         }
255         
256         return NULL;
257 }
258
259 #if 0  // disabled, as some intel cards have problems with this
260 /* Draw a simple diamond shape with a filled in center (in screen space) */
261 static void draw_key_but(int x, int y, short w, short h, int sel)
262 {
263         int xmin= x, ymin= y;
264         int xmax= x+w-1, ymax= y+h-1;
265         int xc= (xmin+xmax)/2, yc= (ymin+ymax)/2;
266         
267         /* interior - hardcoded colors (for selected and unselected only) */
268         if (sel) glColor3ub(0xF1, 0xCA, 0x13);
269         else glColor3ub(0xE9, 0xE9, 0xE9);
270         
271         glBegin(GL_QUADS);
272         glVertex2i(xc, ymin);
273         glVertex2i(xmax, yc);
274         glVertex2i(xc, ymax);
275         glVertex2i(xmin, yc);
276         glEnd();
277         
278         
279         /* outline */
280         glColor3ub(0, 0, 0);
281         
282         glBegin(GL_LINE_LOOP);
283         glVertex2i(xc, ymin);
284         glVertex2i(xmax, yc);
285         glVertex2i(xc, ymax);
286         glVertex2i(xmin, yc);
287         glEnd();
288 }
289 #endif
290
291 static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, float ypos)
292 {
293         ActKeyColumn *ak;
294         ActKeyBlock *ab;
295         
296         glEnable(GL_BLEND);
297         
298         /* draw keyblocks */
299         if (blocks) {
300                 for (ab= blocks->first; ab; ab= ab->next) {
301                         short startCurves, endCurves, totCurves;
302                         
303                         /* find out how many curves occur at each keyframe */
304                         ak= cfra_find_actkeycolumn(keys, ab->start);
305                         startCurves = (ak)? ak->totcurve: 0;
306                         
307                         ak= cfra_find_actkeycolumn(keys, ab->end);
308                         endCurves = (ak)? ak->totcurve: 0;
309                         
310                         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
311                         if (!startCurves && !endCurves) 
312                                 continue;
313                         else
314                                 totCurves = (startCurves>endCurves)? endCurves: startCurves;
315                                 
316                         if (ab->totcurve >= totCurves) {
317                                 int sc_xa, sc_xb, sc_ya, sc_yb;
318                                 
319                                 /* get co-ordinates of block */
320                                 gla2DDrawTranslatePt(di, ab->start, ypos, &sc_xa, &sc_ya);
321                                 gla2DDrawTranslatePt(di, ab->end, ypos, &sc_xb, &sc_yb);
322                                 
323                                 /* draw block */
324                                 if (ab->sel)
325                                         UI_ThemeColor4(TH_STRIP_SELECT);
326                                 else
327                                         UI_ThemeColor4(TH_STRIP);
328                                 glRectf((float)sc_xa, (float)sc_ya-3, (float)sc_xb, (float)sc_yb+5);
329                         }
330                 }
331         }
332         
333         /* draw keys */
334         if (keys) {
335                 for (ak= keys->first; ak; ak= ak->next) {
336                         int sc_x, sc_y;
337                         
338                         /* get co-ordinate to draw at */
339                         gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y);
340                         
341                         /* draw using icons - old way which is slower but more proven */
342                         if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f);
343                         else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f);
344                         
345                         /* draw using OpenGL - slightly uglier but faster */
346                         //      NOTE: disabled for now, as some intel cards seem to have problems with this
347                         //draw_key_but(sc_x-5, sc_y-4, 11, 11, (ak->sel & SELECT));
348                 }       
349         }
350         
351         glDisable(GL_BLEND);
352 }
353
354 /* *************************** Channel Drawing Funcs *************************** */
355
356 void draw_object_channel(gla2DDrawInfo *di, ActKeysInc *aki, Object *ob, float ypos)
357 {
358         ListBase keys = {0, 0};
359         ListBase blocks = {0, 0};
360
361         ob_to_keylist(ob, &keys, &blocks, aki);
362         draw_keylist(di, &keys, &blocks, ypos);
363         
364         BLI_freelistN(&keys);
365         BLI_freelistN(&blocks);
366 }
367
368 void draw_ipo_channel(gla2DDrawInfo *di, ActKeysInc *aki, Ipo *ipo, float ypos)
369 {
370         ListBase keys = {0, 0};
371         ListBase blocks = {0, 0};
372
373         ipo_to_keylist(ipo, &keys, &blocks, aki);
374         draw_keylist(di, &keys, &blocks, ypos);
375         
376         BLI_freelistN(&keys);
377         BLI_freelistN(&blocks);
378 }
379
380 void draw_icu_channel(gla2DDrawInfo *di, ActKeysInc *aki, IpoCurve *icu, float ypos)
381 {
382         ListBase keys = {0, 0};
383         ListBase blocks = {0, 0};
384
385         icu_to_keylist(icu, &keys, &blocks, aki);
386         draw_keylist(di, &keys, &blocks, ypos);
387         
388         BLI_freelistN(&keys);
389         BLI_freelistN(&blocks);
390 }
391
392 void draw_agroup_channel(gla2DDrawInfo *di, ActKeysInc *aki, bActionGroup *agrp, float ypos)
393 {
394         ListBase keys = {0, 0};
395         ListBase blocks = {0, 0};
396
397         agroup_to_keylist(agrp, &keys, &blocks, aki);
398         draw_keylist(di, &keys, &blocks, ypos);
399         
400         BLI_freelistN(&keys);
401         BLI_freelistN(&blocks);
402 }
403
404 void draw_action_channel(gla2DDrawInfo *di, ActKeysInc *aki, bAction *act, float ypos)
405 {
406         ListBase keys = {0, 0};
407         ListBase blocks = {0, 0};
408
409         action_to_keylist(act, &keys, &blocks, aki);
410         draw_keylist(di, &keys, &blocks, ypos);
411         
412         BLI_freelistN(&keys);
413         BLI_freelistN(&blocks);
414 }
415
416 void draw_gpl_channel(gla2DDrawInfo *di, ActKeysInc *aki, bGPDlayer *gpl, float ypos)
417 {
418         ListBase keys = {0, 0};
419         
420         gpl_to_keylist(gpl, &keys, NULL, aki);
421         draw_keylist(di, &keys, NULL, ypos);
422         BLI_freelistN(&keys);
423 }
424
425 /* *************************** Keyframe List Conversions *************************** */
426
427 void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
428 {
429         bConstraintChannel *conchan;
430         Key *key= ob_get_key(ob);
431
432         if (ob) {
433                 bDopeSheet *ads= (aki)? (aki->ads) : NULL;
434                 int filterflag;
435                 
436                 /* get filterflag */
437                 if (ads)
438                         filterflag= ads->filterflag;
439                 else if ((aki) && (aki->actmode == -1)) /* only set like this by NLA */
440                         filterflag= ADS_FILTER_NLADUMMY;
441                 else
442                         filterflag= 0;
443                 
444                 /* Add object keyframes */
445                 if ((ob->ipo) && !(filterflag & ADS_FILTER_NOIPOS))
446                         ipo_to_keylist(ob->ipo, keys, blocks, aki);
447                 
448                 /* Add action keyframes */
449                 if ((ob->action) && !(filterflag & ADS_FILTER_NOACTS))
450                         action_nlascaled_to_keylist(ob, ob->action, keys, blocks, aki);
451                 
452                 /* Add shapekey keyframes (only if dopesheet allows, if it is available) */
453                 if ((key && key->ipo) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
454                         ipo_to_keylist(key->ipo, keys, blocks, aki);
455                         
456                 /* Add material keyframes (only if dopesheet allows, if it is available) */
457                 if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) {
458                         short a;
459                         
460                         for (a=0; a<ob->totcol; a++) {
461                                 Material *ma= give_current_material(ob, a);
462                                 
463                                 if (ELEM(NULL, ma, ma->ipo) == 0)
464                                         ipo_to_keylist(ma->ipo, keys, blocks, aki);
465                         }
466                 }
467                         
468                 /* Add object data keyframes */
469                 switch (ob->type) {
470                         case OB_CAMERA: /* ------- Camera ------------ */
471                         {
472                                 Camera *ca= (Camera *)ob->data;
473                                 if ((ca->ipo) && !(filterflag & ADS_FILTER_NOCAM))
474                                         ipo_to_keylist(ca->ipo, keys, blocks, aki);
475                         }
476                                 break;
477                         case OB_LAMP: /* ---------- Lamp ----------- */
478                         {
479                                 Lamp *la= (Lamp *)ob->data;
480                                 if ((la->ipo) && !(filterflag & ADS_FILTER_NOLAM))
481                                         ipo_to_keylist(la->ipo, keys, blocks, aki);
482                         }
483                                 break;
484                         case OB_CURVE: /* ------- Curve ---------- */
485                         {
486                                 Curve *cu= (Curve *)ob->data;
487                                 if ((cu->ipo) && !(filterflag & ADS_FILTER_NOCUR))
488                                         ipo_to_keylist(cu->ipo, keys, blocks, aki);
489                         }
490                                 break;
491                 }
492                 
493                 /* Add constraint keyframes */
494                 if (!(filterflag & ADS_FILTER_NOCONSTRAINTS)) {
495                         for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) {
496                                 if (conchan->ipo)
497                                         ipo_to_keylist(conchan->ipo, keys, blocks, aki);                
498                         }
499                 }
500         }
501 }
502
503 static short bezt_in_aki_range (ActKeysInc *aki, BezTriple *bezt)
504 {
505         /* when aki == NULL, we don't care about range */
506         if (aki == NULL) 
507                 return 1;
508                 
509         /* if start and end are both 0, then don't care about range */
510         if (IS_EQ(aki->start, 0) && IS_EQ(aki->end, 0))
511                 return 1;
512                 
513         /* if nla-scaling is in effect, apply appropriate scaling adjustments */
514 #if 0 // XXX this was from some buggy code... do not port for now
515         if (aki->ob) {
516                 float frame= get_action_frame_inv(aki->ob, bezt->vec[1][0]);
517                 return IN_RANGE(frame, aki->start, aki->end);
518         }
519         else {
520                 /* check if in range */
521                 return IN_RANGE(bezt->vec[1][0], aki->start, aki->end);
522         }
523 #endif // XXX this was from some buggy code... do not port for now
524         return 1;
525 }
526
527 void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
528 {
529         BezTriple *bezt;
530         ActKeyColumn *ak, *ak2;
531         ActKeyBlock *ab, *ab2;
532         int v;
533         
534         if (icu && icu->totvert) {
535                 /* loop through beztriples, making ActKeys and ActKeyBlocks */
536                 bezt= icu->bezt;
537                 
538                 for (v=0; v<icu->totvert; v++, bezt++) {
539                         /* only if keyframe is in range (optimisation) */
540                         if (bezt_in_aki_range(aki, bezt)) {
541                                 add_bezt_to_keycolumnslist(keys, bezt);
542                                 if (blocks) add_bezt_to_keyblockslist(blocks, icu, v);
543                         }
544                 }
545                 
546                 /* update the number of curves that elements have appeared in  */
547                 if (keys) {
548                         for (ak=keys->first, ak2=keys->last; ak && ak2; ak=ak->next, ak2=ak2->prev) {
549                                 if (ak->modified) {
550                                         ak->modified = 0;
551                                         ak->totcurve += 1;
552                                 }
553                                 
554                                 if (ak == ak2)
555                                         break;
556                                 
557                                 if (ak2->modified) {
558                                         ak2->modified = 0;
559                                         ak2->totcurve += 1;
560                                 }
561                         }
562                 }
563                 if (blocks) {
564                         for (ab=blocks->first, ab2=blocks->last; ab && ab2; ab=ab->next, ab2=ab2->prev) {
565                                 if (ab->modified) {
566                                         ab->modified = 0;
567                                         ab->totcurve += 1;
568                                 }
569                                 
570                                 if (ab == ab2)
571                                         break;
572                                 
573                                 if (ab2->modified) {
574                                         ab2->modified = 0;
575                                         ab2->totcurve += 1;
576                                 }
577                         }
578                 }
579         }
580 }
581
582 void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
583 {
584         IpoCurve *icu;
585         
586         if (ipo) {
587                 for (icu= ipo->curve.first; icu; icu= icu->next)
588                         icu_to_keylist(icu, keys, blocks, aki);
589         }
590 }
591
592 void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
593 {
594         bActionChannel *achan;
595         bConstraintChannel *conchan;
596
597         if (agrp) {
598                 /* loop through action channels */
599                 for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
600                         if (VISIBLE_ACHAN(achan)) {
601                                 /* firstly, add keys from action channel's ipo block */
602                                 if (achan->ipo)
603                                         ipo_to_keylist(achan->ipo, keys, blocks, aki);
604                                 
605                                 /* then, add keys from constraint channels */
606                                 for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
607                                         if (conchan->ipo)
608                                                 ipo_to_keylist(conchan->ipo, keys, blocks, aki);
609                                 }
610                         }
611                 }
612         }
613 }
614
615 void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
616 {
617         bActionChannel *achan;
618         bConstraintChannel *conchan;
619
620         if (act) {
621                 /* loop through action channels */
622                 for (achan= act->chanbase.first; achan; achan= achan->next) {
623                         /* firstly, add keys from action channel's ipo block */
624                         if (achan->ipo)
625                                 ipo_to_keylist(achan->ipo, keys, blocks, aki);
626                         
627                         /* then, add keys from constraint channels */
628                         for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
629                                 if (conchan->ipo)
630                                         ipo_to_keylist(conchan->ipo, keys, blocks, aki);
631                         }
632                 }
633         }
634 }
635
636 void action_nlascaled_to_keylist(Object *ob, bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
637 {
638         bActionChannel *achan;
639         bConstraintChannel *conchan;
640         Object *oldob= NULL;
641         
642         /* although apply and clearing NLA-scaling pre-post creating keylist does impact on performance,
643          * the effects should be fairly minimal, as we're already going through the keyframes multiple times 
644          * already for blocks too...
645          */
646         if (act) {      
647                 /* if 'aki' is provided, store it's current ob to restore later as it might not be the same */
648                 if (aki) {
649                         oldob= aki->ob;
650                         aki->ob= ob;
651                 }
652                 
653                 /* loop through action channels */
654                 for (achan= act->chanbase.first; achan; achan= achan->next) {
655                         /* firstly, add keys from action channel's ipo block 
656                          *      - scaling correction only does times for center-points, so should be faster
657                          */
658                         if (achan->ipo) {
659                                 ANIM_nla_mapping_apply_ipo(ob, achan->ipo, 0, 1);
660                                 ipo_to_keylist(achan->ipo, keys, blocks, aki);
661                                 ANIM_nla_mapping_apply_ipo(ob, achan->ipo, 1, 1);
662                         }
663                         
664                         /* then, add keys from constraint channels 
665                          *      - scaling correction only does times for center-points, so should be faster
666                          */
667                         for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
668                                 if (conchan->ipo) {
669                                         ANIM_nla_mapping_apply_ipo(ob, conchan->ipo, 0, 1);
670                                         ipo_to_keylist(conchan->ipo, keys, blocks, aki);
671                                         ANIM_nla_mapping_apply_ipo(ob, conchan->ipo, 1, 1);
672                                 }
673                         }
674                 }
675                 
676                 /* if 'aki' is provided, restore ob */
677                 if (aki)
678                         aki->ob= oldob;
679         }
680 }
681
682 void gpl_to_keylist(bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
683 {
684         bGPDframe *gpf;
685         ActKeyColumn *ak;
686         
687         if (gpl && keys) {
688                 /* loop over frames, converting directly to 'keyframes' (should be in order too) */
689                 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
690                         ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
691                         BLI_addtail(keys, ak);
692                         
693                         ak->cfra= (float)gpf->framenum;
694                         ak->modified = 1;
695                         ak->handle_type= 0; 
696                         
697                         if (gpf->flag & GP_FRAME_SELECT)
698                                 ak->sel = SELECT;
699                         else
700                                 ak->sel = 0;
701                 }
702         }
703 }
704