4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): Joshua Leung (full recode)
27 * ***** END GPL LICENSE BLOCK *****
30 /* System includes ----------------------------------------------------- */
41 #include "MEM_guardedalloc.h"
43 #include "BLI_blenlib.h"
44 #include "BLI_arithb.h"
45 #include "BLI_dlrbTree.h"
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"
67 #include "BKE_action.h"
68 #include "BKE_depsgraph.h"
69 #include "BKE_fcurve.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"
78 #include "BIF_glutil.h"
80 #include "UI_interface.h"
81 #include "UI_interface_icons.h"
82 #include "UI_resources.h"
83 #include "UI_view2d.h"
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"
91 /* *************************** Keyframe Processing *************************** */
93 /* Create a ActKeyColumn from a BezTriple */
94 static ActKeyColumn *bezt_to_new_actkeycolumn(BezTriple *bezt)
96 ActKeyColumn *ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
98 /* store settings based on state of BezTriple */
99 ak->cfra= bezt->vec[1][0];
100 ak->sel= BEZSELECTED(bezt) ? SELECT : 0;
102 // TODO: handle type = bezt->h1 or bezt->h2
105 /* set 'modified', since this is used to identify long keyframes */
111 /* Add the given BezTriple to the given 'list' of Keyframes */
112 static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt)
114 ActKeyColumn *new_ak=NULL;
116 if ELEM(NULL, keys, bezt) return;
118 /* if there are no keys already, just add as root */
119 if (keys->root == NULL) {
120 /* just add this as the root, then call the tree-balancing functions to validate */
121 new_ak= bezt_to_new_actkeycolumn(bezt);
122 keys->root= (DLRBT_Node *)new_ak;
125 ActKeyColumn *ak, *akp=NULL, *akn=NULL;
127 /* traverse tree to find an existing entry to update the status of,
128 * or a suitable point to add at
130 for (ak= keys->root; ak; akp= ak, ak= akn) {
131 /* check if this is a match, or whether we go left or right */
132 if (ak->cfra == bezt->vec[1][0]) {
133 /* set selection status and 'touched' status */
134 if (BEZSELECTED(bezt)) ak->sel = SELECT;
137 /* done... no need to insert */
141 ActKeyColumn **aknp= NULL;
143 /* check if go left or right, but if not available, add new node */
144 if (ak->cfra < bezt->vec[1][0])
149 /* if this does not exist, add a new node, otherwise continue... */
151 /* add a new node representing this, and attach it to the relevant place */
152 new_ak= bezt_to_new_actkeycolumn(bezt);
163 /* now, balance the tree taking into account this newly added node */
164 BLI_dlrbTree_insert(keys, (DLRBT_Node *)new_ak);
168 /* Create a ActKeyColumn for a pair of BezTriples */
169 static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
171 ActKeyBlock *ab= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
173 ab->start= prev->vec[1][0];
174 ab->end= beztn->vec[1][0];
175 ab->val= beztn->vec[1][1];
177 ab->sel= (BEZSELECTED(prev) || BEZSELECTED(beztn)) ? SELECT : 0;
183 static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, FCurve *fcu, int index)
185 ActKeyBlock *new_ab= NULL;
186 BezTriple *beztn=NULL, *prev=NULL;
191 beztn= (fcu->bezt + index);
193 /* we need to go through all beztriples, as they may not be in order (i.e. during transform) */
194 // TODO: this seems to be a bit of a bottleneck
195 for (v=0, bezt=fcu->bezt; v < fcu->totvert; v++, bezt++) {
196 /* skip if beztriple is current */
198 /* check if beztriple is immediately before */
199 if (beztn->vec[1][0] > bezt->vec[1][0]) {
200 /* check if closer than previous was */
202 if (prev->vec[1][0] < bezt->vec[1][0])
212 /* check if block needed - same value(s)?
213 * -> firstly, handles must have same central value as each other
214 * -> secondly, handles which control that section of the curve must be constant
216 if ((!prev) || (!beztn)) return;
217 if (IS_EQ(beztn->vec[1][1], prev->vec[1][1])==0) return;
218 if (IS_EQ(beztn->vec[1][1], beztn->vec[0][1])==0) return;
219 if (IS_EQ(prev->vec[1][1], prev->vec[2][1])==0) return;
222 /* if there are no blocks already, just add as root */
223 if (blocks->root == NULL) {
224 /* just add this as the root, then call the tree-balancing functions to validate */
225 new_ab= bezts_to_new_actkeyblock(prev, beztn);
226 blocks->root= (DLRBT_Node *)new_ab;
229 ActKeyBlock *ab, *abp=NULL, *abn=NULL;
231 /* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
232 * Note: we can't search from end to try to optimise this as it causes errors there's
233 * an A ___ B |---| B situation
235 // FIXME: here there is a bug where we are trying to get the summary for the following channels
236 // A|--------------|A ______________ B|--------------|B
237 // A|------------------------------------------------|A
238 // A|----|A|---|A|-----------------------------------|A
239 for (ab= blocks->root; ab; abp= ab, ab= abn) {
240 /* check if this is a match, or whether we go left or right */
241 if (ab->start == prev->vec[1][0]) {
242 /* set selection status and 'touched' status */
243 if (BEZSELECTED(beztn)) ab->sel = SELECT;
246 /* done... no need to insert */
250 ActKeyBlock **abnp= NULL;
252 /* check if go left or right, but if not available, add new node */
253 if (ab->start < prev->vec[1][0])
258 /* if this does not exist, add a new node, otherwise continue... */
260 /* add a new node representing this, and attach it to the relevant place */
261 new_ab= bezts_to_new_actkeyblock(prev, beztn);
272 /* now, balance the tree taking into account this newly added node */
273 BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
278 /* Handle the 'touched' status of ActKeyColumn tree nodes */
279 static void set_touched_actkeycolumn (ActKeyColumn *ak)
285 /* deal with self first */
292 set_touched_actkeycolumn(ak->left);
293 set_touched_actkeycolumn(ak->right);
296 /* Handle the 'touched' status of ActKeyBlock tree nodes */
297 static void set_touched_actkeyblock (ActKeyBlock *ab)
303 /* deal with self first */
310 set_touched_actkeyblock(ab->left);
311 set_touched_actkeyblock(ab->right);
314 /* *************************** Keyframe Drawing *************************** */
316 /* helper function - find actkeycolumn that occurs on cframe */
317 static ActKeyColumn *cfra_find_actkeycolumn (ActKeyColumn *ak, float cframe)
323 /* check if this is a match, or whether it is in some subtree */
324 if (cframe < ak->cfra)
325 return cfra_find_actkeycolumn(ak->left, cframe);
326 else if (cframe > ak->cfra)
327 return cfra_find_actkeycolumn(ak->right, cframe);
329 return ak; /* match */
334 /* coordinates for diamond shape */
335 static const float _unit_diamond_shape[4][2] = {
336 {0.0f, 1.0f}, /* top vert */
337 {1.0f, 0.0f}, /* mid-right */
338 {0.0f, -1.0f}, /* bottom vert */
339 {-1.0f, 0.0f} /* mid-left */
342 /* draw a simple diamond shape with OpenGL */
343 void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short mode)
345 static GLuint displist1=0;
346 static GLuint displist2=0;
348 /* initialise 2 display lists for diamond shape - one empty, one filled */
349 if (displist1 == 0) {
350 displist1= glGenLists(1);
351 glNewList(displist1, GL_COMPILE);
353 glBegin(GL_LINE_LOOP);
354 glVertex2fv(_unit_diamond_shape[0]);
355 glVertex2fv(_unit_diamond_shape[1]);
356 glVertex2fv(_unit_diamond_shape[2]);
357 glVertex2fv(_unit_diamond_shape[3]);
361 if (displist2 == 0) {
362 displist2= glGenLists(1);
363 glNewList(displist2, GL_COMPILE);
366 glVertex2fv(_unit_diamond_shape[0]);
367 glVertex2fv(_unit_diamond_shape[1]);
368 glVertex2fv(_unit_diamond_shape[2]);
369 glVertex2fv(_unit_diamond_shape[3]);
374 /* adjust view transform before starting */
375 glTranslatef(x, y, 0.0f);
376 glScalef(1.0f/xscale*hsize, hsize, 1.0f);
378 /* anti-aliased lines for more consistent appearance */
379 glEnable(GL_LINE_SMOOTH);
382 if ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH) {
383 /* interior - hardcoded colors (for selected and unselected only) */
384 if (sel) UI_ThemeColorShade(TH_STRIP_SELECT, 50);
385 else glColor3ub(0xE9, 0xE9, 0xE9);
387 glCallList(displist2);
390 if ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH) {
391 /* exterior - black frame */
394 glCallList(displist1);
397 glDisable(GL_LINE_SMOOTH);
399 /* restore view transform */
400 glScalef(xscale/hsize, 1.0f/hsize, 1.0);
401 glTranslatef(-x, -y, 0.0f);
404 static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos)
412 /* get View2D scaling factor */
413 UI_view2d_getscale(v2d, &xscale, NULL);
417 for (ab= blocks->first; ab; ab= ab->next) {
418 short startCurves, endCurves, totCurves;
420 /* find out how many curves occur at each keyframe */
421 ak= cfra_find_actkeycolumn((ActKeyColumn *)keys->root, ab->start);
422 startCurves = (ak)? ak->totcurve: 0;
424 ak= cfra_find_actkeycolumn((ActKeyColumn *)keys->root, ab->end);
425 endCurves = (ak)? ak->totcurve: 0;
427 /* only draw keyblock if it appears in at all of the keyframes at lowest end */
428 if (!startCurves && !endCurves)
431 totCurves = (startCurves>endCurves)? endCurves: startCurves;
433 if (ab->totcurve >= totCurves) {
436 UI_ThemeColor4(TH_STRIP_SELECT);
438 UI_ThemeColor4(TH_STRIP);
440 glRectf(ab->start, ypos-5, ab->end, ypos+5);
447 for (ak= keys->first; ak; ak= ak->next) {
448 /* optimisation: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
449 * - this might give some improvements, since we current have to flip between view/region matrices
451 if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
454 /* draw using OpenGL - uglier but faster */
455 // NOTE1: a previous version of this didn't work nice for some intel cards
456 // NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3;
457 draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), KEYFRAME_SHAPE_BOTH);
464 /* *************************** Channel Drawing Funcs *************************** */
466 void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
468 DLRBT_Tree keys, blocks;
470 BLI_dlrbTree_init(&keys);
471 BLI_dlrbTree_init(&blocks);
473 scene_to_keylist(ads, sce, &keys, &blocks);
475 BLI_dlrbTree_linkedlist_sync(&keys);
476 BLI_dlrbTree_linkedlist_sync(&blocks);
478 draw_keylist(v2d, &keys, &blocks, ypos);
480 BLI_dlrbTree_free(&keys);
481 BLI_dlrbTree_free(&blocks);
484 void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
486 DLRBT_Tree keys, blocks;
488 BLI_dlrbTree_init(&keys);
489 BLI_dlrbTree_init(&blocks);
491 ob_to_keylist(ads, ob, &keys, &blocks);
493 BLI_dlrbTree_linkedlist_sync(&keys);
494 BLI_dlrbTree_linkedlist_sync(&blocks);
496 draw_keylist(v2d, &keys, &blocks, ypos);
498 BLI_dlrbTree_free(&keys);
499 BLI_dlrbTree_free(&blocks);
502 void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
504 DLRBT_Tree keys, blocks;
506 BLI_dlrbTree_init(&keys);
507 BLI_dlrbTree_init(&blocks);
509 fcurve_to_keylist(adt, fcu, &keys, &blocks);
511 BLI_dlrbTree_linkedlist_sync(&keys);
512 BLI_dlrbTree_linkedlist_sync(&blocks);
514 draw_keylist(v2d, &keys, &blocks, ypos);
516 BLI_dlrbTree_free(&keys);
517 BLI_dlrbTree_free(&blocks);
520 void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
522 DLRBT_Tree keys, blocks;
524 BLI_dlrbTree_init(&keys);
525 BLI_dlrbTree_init(&blocks);
527 agroup_to_keylist(adt, agrp, &keys, &blocks);
529 BLI_dlrbTree_linkedlist_sync(&keys);
530 BLI_dlrbTree_linkedlist_sync(&blocks);
532 draw_keylist(v2d, &keys, &blocks, ypos);
534 BLI_dlrbTree_free(&keys);
535 BLI_dlrbTree_free(&blocks);
538 void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
540 DLRBT_Tree keys, blocks;
542 BLI_dlrbTree_init(&keys);
543 BLI_dlrbTree_init(&blocks);
545 action_to_keylist(adt, act, &keys, &blocks);
547 BLI_dlrbTree_linkedlist_sync(&keys);
548 BLI_dlrbTree_linkedlist_sync(&blocks);
550 draw_keylist(v2d, &keys, &blocks, ypos);
552 BLI_dlrbTree_free(&keys);
553 BLI_dlrbTree_free(&blocks);
556 void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
560 BLI_dlrbTree_init(&keys);
562 gpl_to_keylist(ads, gpl, &keys, NULL);
564 BLI_dlrbTree_linkedlist_sync(&keys);
566 draw_keylist(v2d, &keys, NULL, ypos);
568 BLI_dlrbTree_free(&keys);
571 /* *************************** Keyframe List Conversions *************************** */
573 void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree *blocks)
581 filterflag= ads->filterflag;
586 if ((sce->adt) && !(filterflag & ADS_FILTER_NOSCE)) {
589 // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
591 action_to_keylist(adt, adt->action, keys, blocks);
595 if ((sce->world) && (sce->world->adt) && !(filterflag & ADS_FILTER_NOWOR)) {
596 adt= sce->world->adt;
598 // TODO: when we adapt NLA system, this needs to be the NLA-scaled version
600 action_to_keylist(adt, adt->action, keys, blocks);
605 void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
607 Key *key= ob_get_key(ob);
614 filterflag= ads->filterflag;
618 /* Add action keyframes */
619 if (ob->adt && ob->adt->action)
620 action_to_keylist(ob->adt, ob->adt->action, keys, blocks);
622 /* Add shapekey keyframes (only if dopesheet allows, if it is available) */
623 if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
624 action_to_keylist(key->adt, key->adt->action, keys, blocks);
626 // TODO: restore materials, and object data, etc.
630 void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
635 if (fcu && fcu->totvert && fcu->bezt) {
636 /* apply NLA-mapping (if applicable) */
638 ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 1);
640 /* loop through beztriples, making ActKeys and ActKeyBlocks */
643 for (v=0; v < fcu->totvert; v++, bezt++) {
644 add_bezt_to_keycolumns_list(keys, bezt);
645 if (blocks) add_bezt_to_keyblocks_list(blocks, fcu, v);
648 /* update the number of curves that elements have appeared in */
649 // FIXME: this is broken with the new tree structure for now...
651 set_touched_actkeycolumn(keys->root);
653 set_touched_actkeyblock(blocks->root);
655 /* unapply NLA-mapping if applicable */
656 ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 1);
660 void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, DLRBT_Tree *blocks)
665 /* loop through F-Curves */
666 for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
667 fcurve_to_keylist(adt, fcu, keys, blocks);
672 void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree *blocks)
677 /* loop through F-Curves */
678 for (fcu= act->curves.first; fcu; fcu= fcu->next) {
679 fcurve_to_keylist(adt, fcu, keys, blocks);
685 void gpl_to_keylist(bDopeSheet *ads, bGPDlayer *gpl, DLRBT_Tree *keys, DLRBT_Tree *blocks)
691 /* loop over frames, converting directly to 'keyframes' (should be in order too) */
692 for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
693 ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
694 BLI_addtail((ListBase *)keys, ak);
696 ak->cfra= (float)gpf->framenum;
700 if (gpf->flag & GP_FRAME_SELECT)