Blender V2.61 - r43446

keyframes_draw.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Joshua Leung (full recode)
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 /* System includes ----------------------------------------------------- */
00034 
00035 #include <math.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <float.h>
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "BLI_blenlib.h"
00043 #include "BLI_math.h"
00044 #include "BLI_dlrbTree.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "DNA_anim_types.h"
00048 #include "DNA_armature_types.h"
00049 #include "DNA_camera_types.h"
00050 #include "DNA_object_types.h"
00051 #include "DNA_scene_types.h"
00052 #include "DNA_key_types.h"
00053 #include "DNA_lamp_types.h"
00054 #include "DNA_lattice_types.h"
00055 #include "DNA_mesh_types.h"
00056 #include "DNA_material_types.h"
00057 #include "DNA_meta_types.h"
00058 #include "DNA_node_types.h"
00059 #include "DNA_particle_types.h"
00060 #include "DNA_speaker_types.h"
00061 #include "DNA_world_types.h"
00062 #include "DNA_gpencil_types.h"
00063 
00064 #include "BKE_key.h"
00065 #include "BKE_material.h"
00066 #include "BKE_global.h"     // XXX remove me!
00067 
00068 
00069 #include "BIF_gl.h"
00070 
00071 #include "UI_resources.h"
00072 #include "UI_view2d.h"
00073 
00074 #include "ED_anim_api.h"
00075 #include "ED_keyframes_draw.h"
00076 
00077 /* *************************** Keyframe Processing *************************** */
00078 
00079 /* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
00080 
00081 /* Comparator callback used for ActKeyColumns and cframe float-value pointer */
00082 /* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */
00083 short compare_ak_cfraPtr (void *node, void *data)
00084 {
00085     ActKeyColumn *ak= (ActKeyColumn *)node;
00086     float *cframe= data;
00087     
00088     if (*cframe < ak->cfra)
00089         return -1;
00090     else if (*cframe > ak->cfra)
00091         return 1;
00092     else
00093         return 0;
00094 }
00095 
00096 /* --------------- */
00097 
00098 /* Comparator callback used for ActKeyColumns and BezTriple */
00099 static short compare_ak_bezt (void *node, void *data)
00100 {
00101     ActKeyColumn *ak= (ActKeyColumn *)node;
00102     BezTriple *bezt= (BezTriple *)data;
00103     
00104     if (bezt->vec[1][0] < ak->cfra)
00105         return -1;
00106     else if (bezt->vec[1][0] > ak->cfra)
00107         return 1;
00108     else
00109         return 0;
00110 }
00111 
00112 /* New node callback used for building ActKeyColumns from BezTriples */
00113 static DLRBT_Node *nalloc_ak_bezt (void *data)
00114 {
00115     ActKeyColumn *ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
00116     BezTriple *bezt= (BezTriple *)data;
00117     
00118     /* store settings based on state of BezTriple */
00119     ak->cfra= bezt->vec[1][0];
00120     ak->sel= BEZSELECTED(bezt) ? SELECT : 0;
00121     ak->key_type= BEZKEYTYPE(bezt); 
00122     
00123     /* set 'modified', since this is used to identify long keyframes */
00124     ak->modified = 1;
00125     
00126     return (DLRBT_Node *)ak;
00127 }
00128 
00129 /* Node updater callback used for building ActKeyColumns from BezTriples */
00130 static void nupdate_ak_bezt (void *node, void *data)
00131 {
00132     ActKeyColumn *ak= (ActKeyColumn *)node;
00133     BezTriple *bezt= (BezTriple *)data;
00134     
00135     /* set selection status and 'touched' status */
00136     if (BEZSELECTED(bezt)) ak->sel = SELECT;
00137     ak->modified += 1;
00138     
00139     /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
00140     if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
00141         ak->key_type= BEZT_KEYTYPE_KEYFRAME;
00142 }
00143 
00144 /* ......... */
00145 
00146 /* Comparator callback used for ActKeyColumns and GPencil frame */
00147 static short compare_ak_gpframe (void *node, void *data)
00148 {
00149     ActKeyColumn *ak= (ActKeyColumn *)node;
00150     bGPDframe *gpf= (bGPDframe *)data;
00151     
00152     if (gpf->framenum < ak->cfra)
00153         return -1;
00154     else if (gpf->framenum > ak->cfra)
00155         return 1;
00156     else
00157         return 0;
00158 }
00159 
00160 /* New node callback used for building ActKeyColumns from GPencil frames */
00161 static DLRBT_Node *nalloc_ak_gpframe (void *data)
00162 {
00163     ActKeyColumn *ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
00164     bGPDframe *gpf= (bGPDframe *)data;
00165     
00166     /* store settings based on state of BezTriple */
00167     ak->cfra= gpf->framenum;
00168     ak->sel= (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
00169     
00170     /* set 'modified', since this is used to identify long keyframes */
00171     ak->modified = 1;
00172     
00173     return (DLRBT_Node *)ak;
00174 }
00175 
00176 /* Node updater callback used for building ActKeyColumns from GPencil frames */
00177 static void nupdate_ak_gpframe (void *node, void *data)
00178 {
00179     ActKeyColumn *ak= (ActKeyColumn *)node;
00180     bGPDframe *gpf= (bGPDframe *)data;
00181     
00182     /* set selection status and 'touched' status */
00183     if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT;
00184     ak->modified += 1;
00185 }
00186 
00187 /* --------------- */
00188 
00189 /* Add the given BezTriple to the given 'list' of Keyframes */
00190 static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt)
00191 {
00192     if ELEM(NULL, keys, bezt) 
00193         return;
00194     else
00195         BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt);
00196 }
00197 
00198 /* Add the given GPencil Frame to the given 'list' of Keyframes */
00199 static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf)
00200 {
00201     if ELEM(NULL, keys, gpf) 
00202         return;
00203     else
00204         BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf);
00205 }
00206 
00207 /* ActBeztColumns (Helpers for Long Keyframes) ------------------------------ */
00208 
00209 /* maximum size of default buffer for BezTriple columns */
00210 #define MAX_ABK_BUFSIZE     4
00211 
00212 /* BezTriple Container Node */
00213 // NOTE: only used internally while building Long Keyframes for now, but may be useful externally?
00214 typedef struct ActBeztColumn {
00215     /* Tree Node interface ---------------- */
00216         /* ListBase linkage */
00217     struct ActBeztColumn *next, *prev;
00218     
00219         /* sorting-tree linkage */
00220     struct ActBeztColumn *left, *right; /* 'children' of this node, less than and greater than it (respectively) */
00221     struct ActBeztColumn *parent;       /* parent of this node in the tree */
00222     char tree_col;                      /* DLRB_BLACK or DLRB_RED */
00223     char pad;
00224     
00225     /* BezTriple Store -------------------- */
00226     short numBezts;                     /* number of BezTriples on this frame */
00227     float cfra;                         /* frame that the BezTriples occur on */
00228     
00229     BezTriple *bezts[MAX_ABK_BUFSIZE];  /* buffer of pointers to BezTriples on the same frame */
00230     //BezTriple **bezts_extra;          /* secondary buffer of pointers if need be */
00231 } ActBeztColumn;
00232 
00233 /* --------------- */
00234 
00235 /* Comparator callback used for ActBeztColumns and BezTriple */
00236 static short compare_abk_bezt (void *node, void *data)
00237 {
00238     ActBeztColumn *abk= (ActBeztColumn *)node;
00239     BezTriple *bezt= (BezTriple *)data;
00240     
00241     if (bezt->vec[1][0] < abk->cfra)
00242         return -1;
00243     else if (bezt->vec[1][0] > abk->cfra)
00244         return 1;
00245     else
00246         return 0;
00247 }
00248 
00249 /* New node callback used for building ActBeztColumns from BezTriples */
00250 static DLRBT_Node *nalloc_abk_bezt (void *data)
00251 {
00252     ActBeztColumn *abk= MEM_callocN(sizeof(ActBeztColumn), "ActKeyColumn");
00253     BezTriple *bezt= (BezTriple *)data;
00254     
00255     /* store the BeztTriple in the buffer, and keep track of its frame number */
00256     abk->cfra= bezt->vec[1][0];
00257     abk->bezts[abk->numBezts++]= bezt;
00258     
00259     return (DLRBT_Node *)abk;
00260 }
00261 
00262 /* Node updater callback used for building ActBeztColumns from BezTriples */
00263 static void nupdate_abk_bezt (void *node, void *data)
00264 {
00265     ActBeztColumn *abk= (ActBeztColumn *)node;
00266     BezTriple *bezt= (BezTriple *)data;
00267     
00268     /* just add the BezTriple to the buffer if there's space, or allocate a new one */
00269     if (abk->numBezts >= MAX_ABK_BUFSIZE) {
00270         // TODO: need to allocate new array to cater...
00271         //bezts_extra= MEM_callocN(...);
00272         if(G.f & G_DEBUG)
00273             printf("FIXME: nupdate_abk_bezt() missing case for too many overlapping BezTriples \n");
00274     }
00275     else {
00276         /* just store an extra one */
00277         abk->bezts[abk->numBezts++]= bezt;
00278     }
00279 }
00280 
00281 /* --------------- */
00282 
00283 /* Return the BezTriple in the given ActBeztColumn that matches the requested value */
00284 static BezTriple *abk_get_bezt_with_value (ActBeztColumn *abk, float value)
00285 {
00286     BezTriple *bezt;
00287     int i;
00288     
00289     /* sanity checks */
00290     if (abk == NULL)
00291         return NULL;
00292     
00293     /* look over each BezTriple in this container */
00294     for (i = 0; i < abk->numBezts; i++) {       
00295         /* only do exact match for now... */
00296         if (/*i >= MAX_ABK_BUFSIZE*/0) {
00297             // TODO: this case needs special handling
00298         }
00299         else {
00300             /* just use the default buffer */
00301             bezt= abk->bezts[i];
00302             
00303             if (bezt->vec[1][1] == value)
00304                 return bezt;
00305         }
00306     }
00307     
00308     return NULL;
00309 }
00310 
00311 /* ActKeyBlocks (Long Keyframes) ------------------------------------------ */
00312 
00313 /* Comparator callback used for ActKeyBlock and cframe float-value pointer */
00314 /* NOTE: this is exported to other modules that use the ActKeyBlocks for finding long-keyframes */
00315 short compare_ab_cfraPtr (void *node, void *data)
00316 {
00317     ActKeyBlock *ab= (ActKeyBlock *)node;
00318     float *cframe= data;
00319     
00320     if (*cframe < ab->start)
00321         return -1;
00322     else if (*cframe > ab->start)
00323         return 1;
00324     else
00325         return 0;
00326 }
00327 
00328 /* --------------- */
00329 
00330 /* Create a ActKeyColumn for a pair of BezTriples */
00331 static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
00332 {
00333     ActKeyBlock *ab= MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
00334     
00335     ab->start= prev->vec[1][0];
00336     ab->end= beztn->vec[1][0];
00337     ab->val= beztn->vec[1][1];
00338     
00339     ab->sel= (BEZSELECTED(prev) || BEZSELECTED(beztn)) ? SELECT : 0;
00340     ab->modified = 1;
00341     
00342     return ab;
00343 }
00344 
00345 static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, DLRBT_Tree *beztTree, BezTriple *beztn)
00346 {
00347     ActKeyBlock *new_ab= NULL;
00348     ActBeztColumn *abk;
00349     BezTriple *prev;
00350     
00351     /* get the BezTriple immediately before the given one which has the same value */
00352         /* the keyframes immediately before the ones containing the specified keyframe */
00353     abk= (ActBeztColumn *)BLI_dlrbTree_search_prev(beztTree, compare_abk_bezt, beztn);
00354         /* if applicable, the BezTriple with the same value */
00355     prev= (abk) ? abk_get_bezt_with_value(abk, beztn->vec[1][1]) : NULL;
00356     
00357     /* check if block needed - same value(s)?
00358      *  -> firstly, handles must have same central value as each other
00359      *  -> secondly, handles which control that section of the curve must be constant
00360      */
00361     if ((!prev) || (!beztn)) return;
00362     if (IS_EQF(beztn->vec[1][1], prev->vec[1][1])==0) return;
00363     if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1])==0) return;
00364     if (IS_EQF(prev->vec[1][1], prev->vec[2][1])==0) return;
00365     
00366     
00367     /* if there are no blocks already, just add as root */
00368     if (blocks->root == NULL) {
00369         /* just add this as the root, then call the tree-balancing functions to validate */
00370         new_ab= bezts_to_new_actkeyblock(prev, beztn);
00371         blocks->root= (DLRBT_Node *)new_ab;
00372     }
00373     else {
00374         ActKeyBlock *ab, *abn=NULL;
00375         
00376         /* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
00377          * Note: we can't search from end to try to optimise this as it causes errors there's
00378          *      an A ___ B |---| B situation
00379          */
00380         // FIXME: here there is a bug where we are trying to get the summary for the following channels
00381         //      A|--------------|A ______________ B|--------------|B
00382         //      A|------------------------------------------------|A
00383         //      A|----|A|---|A|-----------------------------------|A
00384         for (ab= blocks->root; ab; ab= abn) {
00385             /* check if this is a match, or whether we go left or right */
00386             if (ab->start == prev->vec[1][0]) {
00387                 /* set selection status and 'touched' status */
00388                 if (BEZSELECTED(beztn)) ab->sel = SELECT;
00389                 ab->modified += 1;
00390                 
00391                 /* done... no need to insert */
00392                 return;
00393             }
00394             else {
00395                 ActKeyBlock **abnp= NULL; 
00396                 
00397                 /* check if go left or right, but if not available, add new node */
00398                 if (ab->start < prev->vec[1][0]) 
00399                     abnp= &ab->right;
00400                 else
00401                     abnp= &ab->left;
00402                     
00403                 /* if this does not exist, add a new node, otherwise continue... */
00404                 if (*abnp == NULL) {
00405                     /* add a new node representing this, and attach it to the relevant place */
00406                     new_ab= bezts_to_new_actkeyblock(prev, beztn);
00407                     new_ab->parent= ab;
00408                     *abnp= new_ab;
00409                     break;
00410                 }
00411                 else
00412                     abn= *abnp;
00413             }
00414         }
00415     }
00416     
00417     /* now, balance the tree taking into account this newly added node */
00418     BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
00419 }
00420 
00421 /* --------- */
00422 
00423 /* Handle the 'touched' status of ActKeyColumn tree nodes */
00424 static void set_touched_actkeycolumn (ActKeyColumn *ak)
00425 {
00426     /* sanity check */
00427     if (ak == NULL)
00428         return;
00429         
00430     /* deal with self first */
00431     if (ak->modified) {
00432         ak->modified= 0;
00433         ak->totcurve++;
00434     }
00435     
00436     /* children */
00437     set_touched_actkeycolumn(ak->left);
00438     set_touched_actkeycolumn(ak->right);
00439 }
00440 
00441 /* Handle the 'touched' status of ActKeyBlock tree nodes */
00442 static void set_touched_actkeyblock (ActKeyBlock *ab)
00443 {
00444     /* sanity check */
00445     if (ab == NULL)
00446         return;
00447         
00448     /* deal with self first */
00449     if (ab->modified) {
00450         ab->modified= 0;
00451         ab->totcurve++;
00452     }
00453     
00454     /* children */
00455     set_touched_actkeyblock(ab->left);
00456     set_touched_actkeyblock(ab->right);
00457 }
00458 
00459 /* --------- */
00460 
00461 /* Checks if ActKeyBlock should exist... */
00462 short actkeyblock_is_valid (ActKeyBlock *ab, DLRBT_Tree *keys)
00463 {
00464     ActKeyColumn *ak;
00465     short startCurves, endCurves, totCurves;
00466     
00467     /* check that block is valid */
00468     if (ab == NULL)
00469         return 0;
00470     
00471     /* find out how many curves occur at each keyframe */
00472     ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->start);
00473     startCurves = (ak)? ak->totcurve: 0;
00474     
00475     ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->end);
00476     endCurves = (ak)? ak->totcurve: 0;
00477     
00478     /* only draw keyblock if it appears in at all of the keyframes at lowest end */
00479     if (!startCurves && !endCurves) 
00480         return 0;
00481     
00482     totCurves = (startCurves>endCurves)? endCurves: startCurves;
00483     return (ab->totcurve >= totCurves);
00484 }
00485 
00486 /* *************************** Keyframe Drawing *************************** */
00487 
00488 /* coordinates for diamond shape */
00489 static const float _unit_diamond_shape[4][2] = {
00490     {0.0f, 1.0f},   /* top vert */
00491     {1.0f, 0.0f},   /* mid-right */
00492     {0.0f, -1.0f},  /* bottom vert */
00493     {-1.0f, 0.0f}   /* mid-left */
00494 }; 
00495 
00496 /* draw a simple diamond shape with OpenGL */
00497 void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha)
00498 {
00499     static GLuint displist1=0;
00500     static GLuint displist2=0;
00501     
00502     /* initialise 2 display lists for diamond shape - one empty, one filled */
00503     if (displist1 == 0) {
00504         displist1= glGenLists(1);
00505             glNewList(displist1, GL_COMPILE);
00506             
00507             glBegin(GL_LINE_LOOP);
00508                 glVertex2fv(_unit_diamond_shape[0]);
00509                 glVertex2fv(_unit_diamond_shape[1]);
00510                 glVertex2fv(_unit_diamond_shape[2]);
00511                 glVertex2fv(_unit_diamond_shape[3]);
00512             glEnd();
00513         glEndList();
00514     }
00515     if (displist2 == 0) {
00516         displist2= glGenLists(1);
00517             glNewList(displist2, GL_COMPILE);
00518             
00519             glBegin(GL_QUADS);
00520                 glVertex2fv(_unit_diamond_shape[0]);
00521                 glVertex2fv(_unit_diamond_shape[1]);
00522                 glVertex2fv(_unit_diamond_shape[2]);
00523                 glVertex2fv(_unit_diamond_shape[3]);
00524             glEnd();
00525         glEndList();
00526     }
00527     
00528     /* tweak size of keyframe shape according to type of keyframe 
00529      *  - 'proper' keyframes have key_type=0, so get drawn at full size
00530      */
00531     hsize -= 0.5f*key_type;
00532     
00533     /* adjust view transform before starting */
00534     glTranslatef(x, y, 0.0f);
00535     glScalef(1.0f/xscale*hsize, hsize, 1.0f);
00536     
00537     /* anti-aliased lines for more consistent appearance */
00538     glEnable(GL_LINE_SMOOTH);
00539     
00540     /* draw! */
00541     if ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH) {
00542         /* interior - hardcoded colors (for selected and unselected only) */
00543         switch (key_type) {
00544             case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames for now */
00545             {
00546                 if (sel) glColor4f(0.33f, 0.75f, 0.93f, alpha);
00547                 else glColor4f(0.70f, 0.86f, 0.91f, alpha);
00548             }
00549                 break;
00550                 
00551             case BEZT_KEYTYPE_EXTREME: /* redish frames for now */
00552             {
00553                 if (sel) glColor4f(0.95f, 0.5f, 0.5f, alpha);
00554                 else glColor4f(0.91f, 0.70f, 0.80f, alpha);
00555             }
00556                 break;
00557                 
00558             case BEZT_KEYTYPE_JITTER: /* greenish frames for now? */
00559             {
00560                 if (sel) glColor4f(0.38f, 0.75f, 0.26f, alpha);
00561                 else glColor4f(0.58f, 0.90f, 0.46f, alpha);
00562             }
00563                 break;
00564                 
00565             case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames for now */
00566             default:
00567             {
00568                 if (sel) UI_ThemeColorShadeAlpha(TH_STRIP_SELECT, 50, -255*(1.0f-alpha));
00569                 else glColor4f(0.91f, 0.91f, 0.91f, alpha);
00570             }
00571                 break;
00572         }
00573         
00574         glCallList(displist2);
00575     }
00576     
00577     if ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH) {
00578         /* exterior - black frame */
00579         glColor4f(0.0f, 0.0f, 0.0f, alpha);
00580         
00581         glCallList(displist1);
00582     }
00583     
00584     glDisable(GL_LINE_SMOOTH);
00585     
00586     /* restore view transform */
00587     glScalef(xscale/hsize, 1.0f/hsize, 1.0);
00588     glTranslatef(-x, -y, 0.0f);
00589 }
00590 
00591 static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, short channelLocked)
00592 {
00593     ActKeyColumn *ak;
00594     ActKeyBlock *ab;
00595     float xscale;
00596     
00597     glEnable(GL_BLEND);
00598     
00599     /* get View2D scaling factor */
00600     UI_view2d_getscale(v2d, &xscale, NULL);
00601     
00602     /* draw keyblocks */
00603     if (blocks) {
00604         for (ab= blocks->first; ab; ab= ab->next) {
00605             if (actkeyblock_is_valid(ab, keys)) {
00606                 /* draw block */
00607                 if (ab->sel)
00608                     UI_ThemeColor4(TH_STRIP_SELECT);
00609                 else
00610                     UI_ThemeColor4(TH_STRIP);
00611                 
00612                 glRectf(ab->start, ypos-5, ab->end, ypos+5);
00613             }
00614         }
00615     }
00616     
00617     /* draw keys */
00618     if (keys) {
00619         /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
00620         // TODO: allow this opacity factor to be themed?
00621         float kalpha = (channelLocked)? 0.35f : 1.0f;
00622         
00623         for (ak= keys->first; ak; ak= ak->next) {
00624             /* optimisation: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw 
00625              *  - this might give some improvements, since we current have to flip between view/region matrices
00626              */
00627             if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
00628                 continue;
00629             
00630             /* draw using OpenGL - uglier but faster */
00631             // NOTE1: a previous version of this didn't work nice for some intel cards
00632             // NOTE2: if we wanted to go back to icons, these are  icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3;
00633             draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, kalpha);
00634         }   
00635     }
00636     
00637     glDisable(GL_BLEND);
00638 }
00639 
00640 /* *************************** Channel Drawing Funcs *************************** */
00641 
00642 void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos)
00643 {
00644     DLRBT_Tree keys, blocks;
00645     
00646     BLI_dlrbTree_init(&keys);
00647     BLI_dlrbTree_init(&blocks);
00648     
00649         summary_to_keylist(ac, &keys, &blocks);
00650     
00651     BLI_dlrbTree_linkedlist_sync(&keys);
00652     BLI_dlrbTree_linkedlist_sync(&blocks);
00653     
00654         draw_keylist(v2d, &keys, &blocks, ypos, 0);
00655     
00656     BLI_dlrbTree_free(&keys);
00657     BLI_dlrbTree_free(&blocks);
00658 }
00659 
00660 void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
00661 {
00662     DLRBT_Tree keys, blocks;
00663     
00664     BLI_dlrbTree_init(&keys);
00665     BLI_dlrbTree_init(&blocks);
00666     
00667         scene_to_keylist(ads, sce, &keys, &blocks);
00668     
00669     BLI_dlrbTree_linkedlist_sync(&keys);
00670     BLI_dlrbTree_linkedlist_sync(&blocks);
00671     
00672         draw_keylist(v2d, &keys, &blocks, ypos, 0);
00673     
00674     BLI_dlrbTree_free(&keys);
00675     BLI_dlrbTree_free(&blocks);
00676 }
00677 
00678 void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
00679 {
00680     DLRBT_Tree keys, blocks;
00681     
00682     BLI_dlrbTree_init(&keys);
00683     BLI_dlrbTree_init(&blocks);
00684     
00685         ob_to_keylist(ads, ob, &keys, &blocks);
00686     
00687     BLI_dlrbTree_linkedlist_sync(&keys);
00688     BLI_dlrbTree_linkedlist_sync(&blocks);
00689     
00690         draw_keylist(v2d, &keys, &blocks, ypos, 0);
00691     
00692     BLI_dlrbTree_free(&keys);
00693     BLI_dlrbTree_free(&blocks);
00694 }
00695 
00696 void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
00697 {
00698     DLRBT_Tree keys, blocks;
00699     
00700     BLI_dlrbTree_init(&keys);
00701     BLI_dlrbTree_init(&blocks);
00702     
00703         fcurve_to_keylist(adt, fcu, &keys, &blocks);
00704     
00705     BLI_dlrbTree_linkedlist_sync(&keys);
00706     BLI_dlrbTree_linkedlist_sync(&blocks);
00707     
00708         draw_keylist(v2d, &keys, &blocks, ypos, (fcu->flag & FCURVE_PROTECTED));
00709     
00710     BLI_dlrbTree_free(&keys);
00711     BLI_dlrbTree_free(&blocks);
00712 }
00713 
00714 void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
00715 {
00716     DLRBT_Tree keys, blocks;
00717     
00718     BLI_dlrbTree_init(&keys);
00719     BLI_dlrbTree_init(&blocks);
00720     
00721         agroup_to_keylist(adt, agrp, &keys, &blocks);
00722     
00723     BLI_dlrbTree_linkedlist_sync(&keys);
00724     BLI_dlrbTree_linkedlist_sync(&blocks);
00725     
00726         draw_keylist(v2d, &keys, &blocks, ypos, (agrp->flag & AGRP_PROTECTED));
00727     
00728     BLI_dlrbTree_free(&keys);
00729     BLI_dlrbTree_free(&blocks);
00730 }
00731 
00732 void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
00733 {
00734     DLRBT_Tree keys, blocks;
00735     
00736     BLI_dlrbTree_init(&keys);
00737     BLI_dlrbTree_init(&blocks);
00738     
00739         action_to_keylist(adt, act, &keys, &blocks);
00740     
00741     BLI_dlrbTree_linkedlist_sync(&keys);
00742     BLI_dlrbTree_linkedlist_sync(&blocks);
00743     
00744         draw_keylist(v2d, &keys, &blocks, ypos, 0);
00745     
00746     BLI_dlrbTree_free(&keys);
00747     BLI_dlrbTree_free(&blocks);
00748 }
00749 
00750 void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
00751 {
00752     DLRBT_Tree keys;
00753     
00754     BLI_dlrbTree_init(&keys);
00755     
00756         gpl_to_keylist(ads, gpl, &keys);
00757     
00758     BLI_dlrbTree_linkedlist_sync(&keys);
00759     
00760         draw_keylist(v2d, &keys, NULL, ypos, (gpl->flag & GP_LAYER_LOCKED));
00761     
00762     BLI_dlrbTree_free(&keys);
00763 }
00764 
00765 /* *************************** Keyframe List Conversions *************************** */
00766 
00767 void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
00768 {
00769     if (ac) {
00770         ListBase anim_data = {NULL, NULL};
00771         bAnimListElem *ale;
00772         int filter;
00773         
00774         /* get F-Curves to take keyframes from */
00775         filter= ANIMFILTER_DATA_VISIBLE; // curves only
00776         ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
00777         
00778         /* loop through each F-Curve, grabbing the keyframes */
00779         for (ale= anim_data.first; ale; ale= ale->next)
00780             fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
00781         
00782         BLI_freelistN(&anim_data);
00783     }
00784 }
00785 
00786 void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree *blocks)
00787 {
00788     bAnimContext ac = {NULL};
00789     ListBase anim_data = {NULL, NULL};
00790     bAnimListElem *ale;
00791     int filter;
00792     
00793     bAnimListElem dummychan = {0};
00794     
00795     if (sce == NULL)
00796         return;
00797     
00798     /* create a dummy wrapper data to work with */
00799     dummychan.type = ANIMTYPE_SCENE;
00800     dummychan.data = sce;
00801     dummychan.id = &sce->id;
00802     dummychan.adt = sce->adt;
00803     
00804     ac.ads = ads;
00805     ac.data = &dummychan;
00806     ac.datatype = ANIMCONT_CHANNEL;
00807     
00808     /* get F-Curves to take keyframes from */
00809     filter= ANIMFILTER_DATA_VISIBLE; // curves only
00810     ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
00811     
00812     /* loop through each F-Curve, grabbing the keyframes */
00813     for (ale= anim_data.first; ale; ale= ale->next)
00814         fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
00815     
00816     BLI_freelistN(&anim_data);
00817 }
00818 
00819 void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
00820 {   
00821     bAnimContext ac = {NULL};
00822     ListBase anim_data = {NULL, NULL};
00823     bAnimListElem *ale;
00824     int filter;
00825     
00826     bAnimListElem dummychan = {0};
00827     Base dummybase = {0};
00828     
00829     if (ob == NULL)
00830         return;
00831     
00832     /* create a dummy wrapper data to work with */
00833     dummybase.object = ob;
00834     
00835     dummychan.type = ANIMTYPE_OBJECT;
00836     dummychan.data = &dummybase;
00837     dummychan.id = &ob->id;
00838     dummychan.adt = ob->adt;
00839     
00840     ac.ads = ads;
00841     ac.data = &dummychan;
00842     ac.datatype = ANIMCONT_CHANNEL;
00843     
00844     /* get F-Curves to take keyframes from */
00845     filter= ANIMFILTER_DATA_VISIBLE; // curves only
00846     ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
00847     
00848     /* loop through each F-Curve, grabbing the keyframes */
00849     for (ale= anim_data.first; ale; ale= ale->next)
00850         fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
00851     
00852     BLI_freelistN(&anim_data);
00853 }
00854 
00855 void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
00856 {
00857     DLRBT_Tree *beztTree = NULL;
00858     BezTriple *bezt;
00859     unsigned int v;
00860 
00861     if (fcu && fcu->totvert && fcu->bezt) {
00862         /* apply NLA-mapping (if applicable) */
00863         if (adt)    
00864             ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
00865         
00866         /* if getting long keyframes too, grab the BezTriples in a BST for 
00867          * accelerated searching...
00868          */
00869         if (blocks) {
00870             /* init new tree */
00871             beztTree= BLI_dlrbTree_new();
00872             
00873             /* populate tree with the BezTriples */
00874             for (v=0, bezt=fcu->bezt; v < fcu->totvert; v++, bezt++)
00875                 BLI_dlrbTree_add(beztTree, compare_abk_bezt, nalloc_abk_bezt, nupdate_abk_bezt, bezt);
00876             
00877             /* make sure that it is suitable for linked-list searching too */
00878             BLI_dlrbTree_linkedlist_sync(beztTree);
00879         }
00880         
00881         /* loop through beztriples, making ActKeysColumns and ActKeyBlocks */
00882         for (v=0, bezt=fcu->bezt; v < fcu->totvert; v++, bezt++) {
00883             add_bezt_to_keycolumns_list(keys, bezt);
00884             if (blocks) add_bezt_to_keyblocks_list(blocks, beztTree, bezt);
00885         }
00886         
00887         /* update the number of curves that elements have appeared in  */
00888         if (keys)
00889             set_touched_actkeycolumn(keys->root);
00890         if (blocks)
00891             set_touched_actkeyblock(blocks->root);
00892             
00893         /* free temp data for building long keyframes */
00894         if (blocks && beztTree) {
00895             BLI_dlrbTree_free(beztTree);
00896             MEM_freeN(beztTree);
00897         }
00898         
00899         /* unapply NLA-mapping if applicable */
00900         if (adt)
00901             ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
00902     }
00903 }
00904 
00905 void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, DLRBT_Tree *blocks)
00906 {
00907     FCurve *fcu;
00908 
00909     if (agrp) {
00910         /* loop through F-Curves */
00911         for (fcu= agrp->channels.first; fcu && fcu->grp==agrp; fcu= fcu->next) {
00912             fcurve_to_keylist(adt, fcu, keys, blocks);
00913         }
00914     }
00915 }
00916 
00917 void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree *blocks)
00918 {
00919     FCurve *fcu;
00920 
00921     if (act) {
00922         /* loop through F-Curves */
00923         for (fcu= act->curves.first; fcu; fcu= fcu->next) {
00924             fcurve_to_keylist(adt, fcu, keys, blocks);
00925         }
00926     }
00927 }
00928 
00929 
00930 void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
00931 {
00932     bGPDframe *gpf;
00933     
00934     if (gpl && keys) {
00935         /* although the frames should already be in an ordered list, they are not suitable for displaying yet */
00936         for (gpf= gpl->frames.first; gpf; gpf= gpf->next)
00937             add_gpframe_to_keycolumns_list(keys, gpf);
00938     }
00939 }
00940