Dopesheet: Keyframe size can be adjusted as part of theme settings
[blender.git] / source / blender / editors / animation / keyframes_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung (full recode)
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/animation/keyframes_draw.c
29  *  \ingroup edanimation
30  */
31
32
33 /* System includes ----------------------------------------------------- */
34
35 #include <math.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <float.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_dlrbTree.h"
43 #include "BLI_utildefines.h"
44
45 #include "DNA_anim_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_gpencil_types.h"
49 #include "DNA_mask_types.h"
50
51 #include "BKE_fcurve.h"
52
53 #include "BIF_gl.h"
54
55 #include "UI_resources.h"
56 #include "UI_view2d.h"
57
58 #include "ED_anim_api.h"
59 #include "ED_keyframes_draw.h"
60
61 /* *************************** Keyframe Processing *************************** */
62
63 /* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
64
65 /* Comparator callback used for ActKeyColumns and cframe float-value pointer */
66 /* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */
67 short compare_ak_cfraPtr(void *node, void *data)
68 {
69         ActKeyColumn *ak = (ActKeyColumn *)node;
70         const float *cframe = data;
71         float val = *cframe;
72         
73         if (IS_EQT(val, ak->cfra, BEZT_BINARYSEARCH_THRESH))
74                 return 0;
75         
76         if (val < ak->cfra)
77                 return -1;
78         else if (val > ak->cfra)
79                 return 1;
80         else
81                 return 0;
82 }
83
84 /* --------------- */
85
86 /* Comparator callback used for ActKeyColumns and BezTriple */
87 static short compare_ak_bezt(void *node, void *data)
88 {
89         ActKeyColumn *ak = (ActKeyColumn *)node;
90         BezTriple *bezt = (BezTriple *)data;
91         
92         if (bezt->vec[1][0] < ak->cfra)
93                 return -1;
94         else if (bezt->vec[1][0] > ak->cfra)
95                 return 1;
96         else
97                 return 0;
98 }
99
100 /* New node callback used for building ActKeyColumns from BezTriples */
101 static DLRBT_Node *nalloc_ak_bezt(void *data)
102 {
103         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
104         BezTriple *bezt = (BezTriple *)data;
105         
106         /* store settings based on state of BezTriple */
107         ak->cfra = bezt->vec[1][0];
108         ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
109         ak->key_type = BEZKEYTYPE(bezt);
110         
111         /* set 'modified', since this is used to identify long keyframes */
112         ak->modified = 1;
113         
114         return (DLRBT_Node *)ak;
115 }
116
117 /* Node updater callback used for building ActKeyColumns from BezTriples */
118 static void nupdate_ak_bezt(void *node, void *data)
119 {
120         ActKeyColumn *ak = (ActKeyColumn *)node;
121         BezTriple *bezt = (BezTriple *)data;
122         
123         /* set selection status and 'touched' status */
124         if (BEZT_ISSEL_ANY(bezt)) ak->sel = SELECT;
125         ak->modified += 1;
126         
127         /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
128         if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
129                 ak->key_type = BEZT_KEYTYPE_KEYFRAME;
130 }
131
132 /* ......... */
133
134 /* Comparator callback used for ActKeyColumns and GPencil frame */
135 static short compare_ak_gpframe(void *node, void *data)
136 {
137         ActKeyColumn *ak = (ActKeyColumn *)node;
138         bGPDframe *gpf = (bGPDframe *)data;
139         
140         if (gpf->framenum < ak->cfra)
141                 return -1;
142         else if (gpf->framenum > ak->cfra)
143                 return 1;
144         else
145                 return 0;
146 }
147
148 /* New node callback used for building ActKeyColumns from GPencil frames */
149 static DLRBT_Node *nalloc_ak_gpframe(void *data)
150 {
151         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
152         bGPDframe *gpf = (bGPDframe *)data;
153         
154         /* store settings based on state of BezTriple */
155         ak->cfra = gpf->framenum;
156         ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
157         ak->key_type = gpf->key_type;
158         
159         /* set 'modified', since this is used to identify long keyframes */
160         ak->modified = 1;
161         
162         return (DLRBT_Node *)ak;
163 }
164
165 /* Node updater callback used for building ActKeyColumns from GPencil frames */
166 static void nupdate_ak_gpframe(void *node, void *data)
167 {
168         ActKeyColumn *ak = (ActKeyColumn *)node;
169         bGPDframe *gpf = (bGPDframe *)data;
170         
171         /* set selection status and 'touched' status */
172         if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT;
173         ak->modified += 1;
174         
175         /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
176         if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME)
177                 ak->key_type = BEZT_KEYTYPE_KEYFRAME;
178 }
179
180 /* ......... */
181
182 /* Comparator callback used for ActKeyColumns and GPencil frame */
183 static short compare_ak_masklayshape(void *node, void *data)
184 {
185         ActKeyColumn *ak = (ActKeyColumn *)node;
186         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
187
188         if (masklay_shape->frame < ak->cfra)
189                 return -1;
190         else if (masklay_shape->frame > ak->cfra)
191                 return 1;
192         else
193                 return 0;
194 }
195
196 /* New node callback used for building ActKeyColumns from GPencil frames */
197 static DLRBT_Node *nalloc_ak_masklayshape(void *data)
198 {
199         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
200         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
201
202         /* store settings based on state of BezTriple */
203         ak->cfra = masklay_shape->frame;
204         ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0;
205
206         /* set 'modified', since this is used to identify long keyframes */
207         ak->modified = 1;
208
209         return (DLRBT_Node *)ak;
210 }
211
212 /* Node updater callback used for building ActKeyColumns from GPencil frames */
213 static void nupdate_ak_masklayshape(void *node, void *data)
214 {
215         ActKeyColumn *ak = (ActKeyColumn *)node;
216         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
217
218         /* set selection status and 'touched' status */
219         if (masklay_shape->flag & MASK_SHAPE_SELECT) ak->sel = SELECT;
220         ak->modified += 1;
221 }
222
223
224 /* --------------- */
225
226 /* Add the given BezTriple to the given 'list' of Keyframes */
227 static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt)
228 {
229         if (ELEM(NULL, keys, bezt))
230                 return;
231         else
232                 BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt);
233 }
234
235 /* Add the given GPencil Frame to the given 'list' of Keyframes */
236 static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf)
237 {
238         if (ELEM(NULL, keys, gpf))
239                 return;
240         else
241                 BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf);
242 }
243
244 /* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */
245 static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape)
246 {
247         if (ELEM(NULL, keys, masklay_shape))
248                 return;
249         else
250                 BLI_dlrbTree_add(keys, compare_ak_masklayshape, nalloc_ak_masklayshape, nupdate_ak_masklayshape, masklay_shape);
251 }
252
253 /* ActKeyBlocks (Long Keyframes) ------------------------------------------ */
254
255 /* Comparator callback used for ActKeyBlock and cframe float-value pointer */
256 /* NOTE: this is exported to other modules that use the ActKeyBlocks for finding long-keyframes */
257 short compare_ab_cfraPtr(void *node, void *data)
258 {
259         ActKeyBlock *ab = (ActKeyBlock *)node;
260         const float *cframe = data;
261         float val = *cframe;
262         
263         if (val < ab->start)
264                 return -1;
265         else if (val > ab->start)
266                 return 1;
267         else
268                 return 0;
269 }
270
271 /* --------------- */
272
273 /* Create a ActKeyColumn for a pair of BezTriples */
274 static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
275 {
276         ActKeyBlock *ab = MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
277         
278         ab->start = prev->vec[1][0];
279         ab->end = beztn->vec[1][0];
280         ab->val = beztn->vec[1][1];
281         
282         ab->sel = (BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn)) ? SELECT : 0;
283         ab->modified = 1;
284         
285         return ab;
286 }
287
288 static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt, BezTriple *beztn)
289 {
290         ActKeyBlock *new_ab = NULL;
291         BezTriple *prev = NULL;
292         
293         /* get the BezTriple immediately before the given one which has the same value */
294         if (beztn != first_bezt) {
295                 /* XXX: Unless I'm overlooking some details from the past, this should be sufficient? 
296                  *      The old code did some elaborate stuff trying to find keyframe columns for
297                  *      the given BezTriple, then step backwards to the column before that, and find
298                  *      an appropriate BezTriple with matching values there. Maybe that was warranted
299                  *      in the past, but now, that list is only ever filled with keyframes from the 
300                  *      current FCurve.
301                  *
302                  *      -- Aligorith (20140415)
303                  */
304                 prev = beztn - 1;
305         }
306         
307         
308         /* check if block needed - same value(s)?
309          *      -> firstly, handles must have same central value as each other
310          *      -> secondly, handles which control that section of the curve must be constant
311          */
312         if (prev == NULL) return;
313         if (IS_EQF(beztn->vec[1][1], prev->vec[1][1]) == 0) return;
314         
315         if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) == 0) return;
316         if (IS_EQF(prev->vec[1][1], prev->vec[2][1]) == 0) return;
317         
318         
319         /* if there are no blocks already, just add as root */
320         if (blocks->root == NULL) {
321                 /* just add this as the root, then call the tree-balancing functions to validate */
322                 new_ab = bezts_to_new_actkeyblock(prev, beztn);
323                 blocks->root = (DLRBT_Node *)new_ab;
324         }
325         else {
326                 ActKeyBlock *ab, *abn = NULL;
327                 
328                 /* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
329                  * Note: we perform a tree traversal here NOT a standard linked-list traversal...
330                  * Note: we can't search from end to try to optimize this as it causes errors there's
331                  *      an A ___ B |---| B situation
332                  */
333                 // FIXME: here there is a bug where we are trying to get the summary for the following channels
334                 //              A|--------------|A ______________ B|--------------|B
335                 //              A|------------------------------------------------|A
336                 //              A|----|A|---|A|-----------------------------------|A
337                 for (ab = blocks->root; ab; ab = abn) {
338                         /* check if this is a match, or whether we go left or right 
339                          * NOTE: we now use a float threshold to prevent precision errors causing problems with summaries
340                          */
341                         if (IS_EQT(ab->start, prev->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
342                                 /* set selection status and 'touched' status */
343                                 if (BEZT_ISSEL_ANY(beztn)) ab->sel = SELECT;
344                                 ab->modified++;
345                                 
346                                 /* done... no need to insert */
347                                 return;
348                         }
349                         else {
350                                 ActKeyBlock **abnp = NULL; /* branch to go down - used to hook new blocks to parents */
351                                 
352                                 /* check if go left or right, but if not available, add new node */
353                                 if (ab->start < prev->vec[1][0]) 
354                                         abnp = &ab->right;
355                                 else
356                                         abnp = &ab->left;
357                                         
358                                 /* if this does not exist, add a new node, otherwise continue... */
359                                 if (*abnp == NULL) {
360                                         /* add a new node representing this, and attach it to the relevant place */
361                                         new_ab = bezts_to_new_actkeyblock(prev, beztn);
362                                         new_ab->parent = ab;
363                                         *abnp = new_ab;
364                                         break;
365                                 }
366                                 else
367                                         abn = *abnp;
368                         }
369                 }
370         }
371         
372         /* now, balance the tree taking into account this newly added node */
373         BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
374 }
375
376 /* --------- */
377
378 /* Handle the 'touched' status of ActKeyColumn tree nodes */
379 static void set_touched_actkeycolumn(ActKeyColumn *ak)
380 {
381         /* sanity check */
382         if (ak == NULL)
383                 return;
384                 
385         /* deal with self first */
386         if (ak->modified) {
387                 ak->modified = 0;
388                 ak->totcurve++;
389         }
390         
391         /* children */
392         set_touched_actkeycolumn(ak->left);
393         set_touched_actkeycolumn(ak->right);
394 }
395
396 /* Handle the 'touched' status of ActKeyBlock tree nodes */
397 static void set_touched_actkeyblock(ActKeyBlock *ab)
398 {
399         /* sanity check */
400         if (ab == NULL)
401                 return;
402                 
403         /* deal with self first */
404         if (ab->modified) {
405                 ab->modified = 0;
406                 ab->totcurve++;
407         }
408         
409         /* children */
410         set_touched_actkeyblock(ab->left);
411         set_touched_actkeyblock(ab->right);
412 }
413
414 /* --------- */
415
416 /* Checks if ActKeyBlock should exist... */
417 bool actkeyblock_is_valid(ActKeyBlock *ab, DLRBT_Tree *keys)
418 {
419         ActKeyColumn *ak;
420         short startCurves, endCurves, totCurves;
421         
422         /* check that block is valid */
423         if (ab == NULL)
424                 return 0;
425         
426         /* find out how many curves occur at each keyframe */
427         ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->start);
428         startCurves = (ak) ? ak->totcurve : 0;
429         
430         ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->end);
431         endCurves = (ak) ? ak->totcurve : 0;
432         
433         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
434         if (!startCurves && !endCurves) 
435                 return 0;
436         
437         totCurves = (startCurves > endCurves) ? endCurves : startCurves;
438         return (ab->totcurve >= totCurves);
439 }
440
441 /* *************************** Keyframe Drawing *************************** */
442
443 /* coordinates for diamond shape */
444 static const float _unit_diamond_shape[4][2] = {
445         {0.0f, 1.0f},   /* top vert */
446         {1.0f, 0.0f},   /* mid-right */
447         {0.0f, -1.0f},  /* bottom vert */
448         {-1.0f, 0.0f}   /* mid-left */
449 }; 
450
451 /* draw a simple diamond shape with OpenGL */
452 void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha)
453 {
454         static GLuint displist1 = 0;
455         static GLuint displist2 = 0;
456         
457         /* initialize 2 display lists for diamond shape - one empty, one filled */
458         if (displist1 == 0) {
459                 displist1 = glGenLists(1);
460                 glNewList(displist1, GL_COMPILE);
461                         
462                 glBegin(GL_LINE_LOOP);
463                 glVertex2fv(_unit_diamond_shape[0]);
464                 glVertex2fv(_unit_diamond_shape[1]);
465                 glVertex2fv(_unit_diamond_shape[2]);
466                 glVertex2fv(_unit_diamond_shape[3]);
467                 glEnd();
468
469                 glEndList();
470         }
471         if (displist2 == 0) {
472                 displist2 = glGenLists(1);
473                 glNewList(displist2, GL_COMPILE);
474                         
475                 glBegin(GL_QUADS);
476                 glVertex2fv(_unit_diamond_shape[0]);
477                 glVertex2fv(_unit_diamond_shape[1]);
478                 glVertex2fv(_unit_diamond_shape[2]);
479                 glVertex2fv(_unit_diamond_shape[3]);
480                 glEnd();
481
482                 glEndList();
483         }
484         
485         /* tweak size of keyframe shape according to type of keyframe 
486          * - 'proper' keyframes have key_type = 0, so get drawn at full size
487          */
488         hsize -= 0.5f * key_type;
489         
490         /* adjust view transform before starting */
491         glTranslatef(x, y, 0.0f);
492         glScalef(1.0f / xscale * hsize, hsize, 1.0f);
493         
494         /* anti-aliased lines for more consistent appearance */
495         glEnable(GL_LINE_SMOOTH);
496         
497         /* draw! */
498         if (ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH)) {
499                 float inner_col[4];
500                 
501                 /* get interior colors from theme (for selected and unselected only) */
502                 switch (key_type) {
503                         case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
504                         {
505                                 if (sel)  UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN_SELECT, inner_col);
506                                 else UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN, inner_col);
507                                 break;
508                         }
509                         case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
510                         {
511                                 if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME_SELECT, inner_col);
512                                 else UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME, inner_col);
513                                 break;
514                         }
515                         case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
516                         {
517                                 if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_JITTER_SELECT, inner_col);
518                                 else UI_GetThemeColor4fv(TH_KEYTYPE_JITTER, inner_col);
519                                 break;
520                         }
521                         case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
522                         default:
523                         {
524                                 if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME_SELECT, inner_col);
525                                 else UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME, inner_col);
526                                 break;
527                         }
528                 }
529                 
530                 /* NOTE: we don't use the straight alpha from the theme, or else effects such as 
531                  * graying out protected/muted channels doesn't work correctly!
532                  */
533                 inner_col[3] *= alpha;
534                 glColor4fv(inner_col);
535                 
536                 /* draw the "filled in" interior poly now */
537                 glCallList(displist2);
538         }
539         
540         if (ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH)) {
541                 float border_col[4];
542                 
543                 /* exterior - black frame */
544                 if (sel)  UI_GetThemeColor4fv(TH_KEYBORDER_SELECT, border_col);
545                 else  UI_GetThemeColor4fv(TH_KEYBORDER, border_col);
546                 
547                 border_col[3] *= alpha;
548                 glColor4fv(border_col);
549                 
550                 glCallList(displist1);
551         }
552         
553         glDisable(GL_LINE_SMOOTH);
554         
555         /* restore view transform */
556         glScalef(xscale / hsize, 1.0f / hsize, 1.0f);
557         glTranslatef(-x, -y, 0.0f);
558 }
559
560 static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked)
561 {
562         ActKeyColumn *ak;
563         ActKeyBlock *ab;
564         float alpha;
565         float xscale;
566         float iconsize = (U.widget_unit / 4.0f) * yscale_fac;
567         glEnable(GL_BLEND);
568         
569         /* get View2D scaling factor */
570         UI_view2d_scale_get(v2d, &xscale, NULL);
571         
572         /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
573         /* TODO: allow this opacity factor to be themed? */
574         alpha = (channelLocked) ? 0.25f : 1.0f;
575         
576         /* draw keyblocks */
577         if (blocks) {
578                 float sel_color[4], unsel_color[4];
579                 
580                 /* cache colours first */
581                 UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
582                 UI_GetThemeColor4fv(TH_STRIP, unsel_color);
583                 
584                 sel_color[3]   *= alpha;
585                 unsel_color[3] *= alpha;
586                 
587                 /* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */
588                 for (ab = blocks->first; ab; ab = ab->next) {
589                         if (actkeyblock_is_valid(ab, keys)) {
590                                 /* draw block */
591                                 if (ab->sel)
592                                         glColor4fv(sel_color);
593                                 else
594                                         glColor4fv(unsel_color);
595                                 
596                                 glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize);
597                         }
598                 }
599         }
600         
601         /* draw keys */
602         if (keys) {
603                 for (ak = keys->first; ak; ak = ak->next) {
604                         /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
605                          *      - this might give some improvements, since we current have to flip between view/region matrices
606                          */
607                         if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
608                                 continue;
609                         
610                         /* draw using OpenGL - uglier but faster */
611                         /* NOTE1: a previous version of this didn't work nice for some intel cards
612                          * NOTE2: if we wanted to go back to icons, these are  icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */
613                         draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha);
614                 }
615         }
616
617         glDisable(GL_BLEND);
618 }
619
620 /* *************************** Channel Drawing Funcs *************************** */
621
622 void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac)
623 {
624         DLRBT_Tree keys, blocks;
625         
626         BLI_dlrbTree_init(&keys);
627         BLI_dlrbTree_init(&blocks);
628         
629         summary_to_keylist(ac, &keys, &blocks);
630         
631         BLI_dlrbTree_linkedlist_sync(&keys);
632         BLI_dlrbTree_linkedlist_sync(&blocks);
633         
634         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
635         
636         BLI_dlrbTree_free(&keys);
637         BLI_dlrbTree_free(&blocks);
638 }
639
640 void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac)
641 {
642         DLRBT_Tree keys, blocks;
643         
644         BLI_dlrbTree_init(&keys);
645         BLI_dlrbTree_init(&blocks);
646         
647         scene_to_keylist(ads, sce, &keys, &blocks);
648         
649         BLI_dlrbTree_linkedlist_sync(&keys);
650         BLI_dlrbTree_linkedlist_sync(&blocks);
651         
652         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
653         
654         BLI_dlrbTree_free(&keys);
655         BLI_dlrbTree_free(&blocks);
656 }
657
658 void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac)
659 {
660         DLRBT_Tree keys, blocks;
661         
662         BLI_dlrbTree_init(&keys);
663         BLI_dlrbTree_init(&blocks);
664         
665         ob_to_keylist(ads, ob, &keys, &blocks);
666         
667         BLI_dlrbTree_linkedlist_sync(&keys);
668         BLI_dlrbTree_linkedlist_sync(&blocks);
669         
670         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
671         
672         BLI_dlrbTree_free(&keys);
673         BLI_dlrbTree_free(&blocks);
674 }
675
676 void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac)
677 {
678         DLRBT_Tree keys, blocks;
679         
680         bool locked = (fcu->flag & FCURVE_PROTECTED) ||
681                       ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
682                       ((adt && adt->action) && ID_IS_LINKED_DATABLOCK(adt->action));
683         
684         BLI_dlrbTree_init(&keys);
685         BLI_dlrbTree_init(&blocks);
686         
687         fcurve_to_keylist(adt, fcu, &keys, &blocks);
688         
689         BLI_dlrbTree_linkedlist_sync(&keys);
690         BLI_dlrbTree_linkedlist_sync(&blocks);
691         
692         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
693         
694         BLI_dlrbTree_free(&keys);
695         BLI_dlrbTree_free(&blocks);
696 }
697
698 void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac)
699 {
700         DLRBT_Tree keys, blocks;
701         
702         bool locked = (agrp->flag & AGRP_PROTECTED) ||
703                       ((adt && adt->action) && ID_IS_LINKED_DATABLOCK(adt->action));
704         
705         BLI_dlrbTree_init(&keys);
706         BLI_dlrbTree_init(&blocks);
707         
708         agroup_to_keylist(adt, agrp, &keys, &blocks);
709         
710         BLI_dlrbTree_linkedlist_sync(&keys);
711         BLI_dlrbTree_linkedlist_sync(&blocks);
712         
713         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
714         
715         BLI_dlrbTree_free(&keys);
716         BLI_dlrbTree_free(&blocks);
717 }
718
719 void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac)
720 {
721         DLRBT_Tree keys, blocks;
722         
723         bool locked = (act && ID_IS_LINKED_DATABLOCK(act));
724         
725         BLI_dlrbTree_init(&keys);
726         BLI_dlrbTree_init(&blocks);
727         
728         action_to_keylist(adt, act, &keys, &blocks);
729         
730         BLI_dlrbTree_linkedlist_sync(&keys);
731         BLI_dlrbTree_linkedlist_sync(&blocks);
732         
733         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
734         
735         BLI_dlrbTree_free(&keys);
736         BLI_dlrbTree_free(&blocks);
737 }
738
739 void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac)
740 {
741         DLRBT_Tree keys;
742         
743         BLI_dlrbTree_init(&keys);
744         
745         gpencil_to_keylist(ads, gpd, &keys);
746         
747         BLI_dlrbTree_linkedlist_sync(&keys);
748         
749         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, false);
750         
751         BLI_dlrbTree_free(&keys);
752 }
753
754 void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac)
755 {
756         DLRBT_Tree keys;
757         
758         bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
759         
760         BLI_dlrbTree_init(&keys);
761         
762         gpl_to_keylist(ads, gpl, &keys);
763         
764         BLI_dlrbTree_linkedlist_sync(&keys);
765         
766         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
767         
768         BLI_dlrbTree_free(&keys);
769 }
770
771 void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos, float yscale_fac)
772 {
773         DLRBT_Tree keys;
774         
775         bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
776         
777         BLI_dlrbTree_init(&keys);
778         
779         mask_to_keylist(ads, masklay, &keys);
780         
781         BLI_dlrbTree_linkedlist_sync(&keys);
782         
783         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
784         
785         BLI_dlrbTree_free(&keys);
786 }
787
788 /* *************************** Keyframe List Conversions *************************** */
789
790 void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
791 {
792         if (ac) {
793                 ListBase anim_data = {NULL, NULL};
794                 bAnimListElem *ale;
795                 int filter;
796                 
797                 /* get F-Curves to take keyframes from */
798                 filter = ANIMFILTER_DATA_VISIBLE;
799                 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
800                 
801                 /* loop through each F-Curve, grabbing the keyframes */
802                 for (ale = anim_data.first; ale; ale = ale->next) {
803                         /* Why not use all #eAnim_KeyType here?
804                          * All of the other key types are actually "summaries" themselves, and will just end up duplicating stuff
805                          * that comes up through standard filtering of just F-Curves.
806                          * Given the way that these work, there isn't really any benefit at all from including them. - Aligorith */
807
808                         switch (ale->datatype) {
809                                 case ALE_FCURVE:
810                                         fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
811                                         break;
812                                 case ALE_MASKLAY:
813                                         mask_to_keylist(ac->ads, ale->data, keys);
814                                         break;
815                                 case ALE_GPFRAME:
816                                         gpl_to_keylist(ac->ads, ale->data, keys);
817                                         break;
818                                 default:
819                                         // printf("%s: datatype %d unhandled\n", __func__, ale->datatype);
820                                         break;
821                         }
822                 }
823                 
824                 ANIM_animdata_freelist(&anim_data);
825         }
826 }
827
828 void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree *blocks)
829 {
830         bAnimContext ac = {NULL};
831         ListBase anim_data = {NULL, NULL};
832         bAnimListElem *ale;
833         int filter;
834         
835         bAnimListElem dummychan = {NULL};
836         
837         if (sce == NULL)
838                 return;
839         
840         /* create a dummy wrapper data to work with */
841         dummychan.type = ANIMTYPE_SCENE;
842         dummychan.data = sce;
843         dummychan.id = &sce->id;
844         dummychan.adt = sce->adt;
845         
846         ac.ads = ads;
847         ac.data = &dummychan;
848         ac.datatype = ANIMCONT_CHANNEL;
849         
850         /* get F-Curves to take keyframes from */
851         filter = ANIMFILTER_DATA_VISIBLE; // curves only
852         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
853         
854         /* loop through each F-Curve, grabbing the keyframes */
855         for (ale = anim_data.first; ale; ale = ale->next)
856                 fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
857         
858         ANIM_animdata_freelist(&anim_data);
859 }
860
861 void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
862 {       
863         bAnimContext ac = {NULL};
864         ListBase anim_data = {NULL, NULL};
865         bAnimListElem *ale;
866         int filter;
867         
868         bAnimListElem dummychan = {NULL};
869         Base dummybase = {NULL};
870         
871         if (ob == NULL)
872                 return;
873         
874         /* create a dummy wrapper data to work with */
875         dummybase.object = ob;
876         
877         dummychan.type = ANIMTYPE_OBJECT;
878         dummychan.data = &dummybase;
879         dummychan.id = &ob->id;
880         dummychan.adt = ob->adt;
881         
882         ac.ads = ads;
883         ac.data = &dummychan;
884         ac.datatype = ANIMCONT_CHANNEL;
885         
886         /* get F-Curves to take keyframes from */
887         filter = ANIMFILTER_DATA_VISIBLE; // curves only
888         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
889         
890         /* loop through each F-Curve, grabbing the keyframes */
891         for (ale = anim_data.first; ale; ale = ale->next)
892                 fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
893         
894         ANIM_animdata_freelist(&anim_data);
895 }
896
897 void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
898 {
899         BezTriple *bezt;
900         unsigned int v;
901
902         if (fcu && fcu->totvert && fcu->bezt) {
903                 /* apply NLA-mapping (if applicable) */
904                 if (adt)
905                         ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
906                 
907                 /* loop through beztriples, making ActKeysColumns and ActKeyBlocks */
908                 for (v = 0, bezt = fcu->bezt; v < fcu->totvert; v++, bezt++) {
909                         add_bezt_to_keycolumns_list(keys, bezt);
910                         if (blocks) add_bezt_to_keyblocks_list(blocks, fcu->bezt, bezt);
911                 }
912                 
913                 /* update the number of curves that elements have appeared in  */
914                 if (keys)
915                         set_touched_actkeycolumn(keys->root);
916                 if (blocks)
917                         set_touched_actkeyblock(blocks->root);
918                 
919                 /* unapply NLA-mapping if applicable */
920                 if (adt)
921                         ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
922         }
923 }
924
925 void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, DLRBT_Tree *blocks)
926 {
927         FCurve *fcu;
928
929         if (agrp) {
930                 /* loop through F-Curves */
931                 for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) {
932                         fcurve_to_keylist(adt, fcu, keys, blocks);
933                 }
934         }
935 }
936
937 void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree *blocks)
938 {
939         FCurve *fcu;
940
941         if (act) {
942                 /* loop through F-Curves */
943                 for (fcu = act->curves.first; fcu; fcu = fcu->next) {
944                         fcurve_to_keylist(adt, fcu, keys, blocks);
945                 }
946         }
947 }
948
949
950 void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys)
951 {
952         bGPDlayer *gpl;
953         
954         if (gpd && keys) {
955                 /* for now, just aggregate out all the frames, but only for visible layers */
956                 for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
957                         if ((gpl->flag & GP_LAYER_HIDE) == 0) {
958                                 gpl_to_keylist(ads, gpl, keys);
959                         }
960                 }
961         }
962 }
963
964 void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
965 {
966         bGPDframe *gpf;
967         
968         if (gpl && keys) {
969                 /* although the frames should already be in an ordered list, they are not suitable for displaying yet */
970                 for (gpf = gpl->frames.first; gpf; gpf = gpf->next)
971                         add_gpframe_to_keycolumns_list(keys, gpf);
972         }
973 }
974
975 void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys)
976 {
977         MaskLayerShape *masklay_shape;
978
979         if (masklay && keys) {
980                 for (masklay_shape = masklay->splines_shapes.first;
981                      masklay_shape;
982                      masklay_shape = masklay_shape->next)
983                 {
984                         add_masklay_to_keycolumns_list(keys, masklay_shape);
985                 }
986         }
987 }
988