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