Blender  V2.59
graph_utils.c
Go to the documentation of this file.
00001 /*
00002  * $Id: graph_utils.c 35242 2011-02-27 20:29:51Z jesterking $
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.
00021  * All rights reserved.
00022  *
00023  * 
00024  * Contributor(s): Blender Foundation, Joshua Leung
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <string.h>
00035 #include <stdio.h>
00036 #include <math.h>
00037 #include <float.h>
00038 
00039 #include "DNA_anim_types.h"
00040 #include "DNA_space_types.h"
00041 #include "DNA_screen_types.h"
00042 
00043 #include "MEM_guardedalloc.h"
00044 
00045 #include "BLI_math.h"
00046 #include "BLI_blenlib.h"
00047 #include "BLI_editVert.h"
00048 #include "BLI_rand.h"
00049 
00050 #include "BKE_context.h"
00051 #include "BKE_fcurve.h"
00052 
00053 
00054 #include "WM_api.h"
00055 
00056 
00057 #include "ED_anim_api.h"
00058 
00059 
00060 #include "graph_intern.h"       // own include
00061 
00062 /* ************************************************************** */
00063 /* Active F-Curve */
00064 
00065 /* Find 'active' F-Curve. It must be editable, since that's the purpose of these buttons (subject to change).  
00066  * We return the 'wrapper' since it contains valuable context info (about hierarchy), which will need to be freed 
00067  * when the caller is done with it.
00068  */
00069 bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
00070 {
00071         ListBase anim_data = {NULL, NULL};
00072         int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE | ANIMFILTER_CURVESONLY);
00073         int items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
00074         
00075         /* We take the first F-Curve only, since some other ones may have had 'active' flag set
00076          * if they were from linked data.
00077          */
00078         if (items) {
00079                 bAnimListElem *ale= (bAnimListElem *)anim_data.first;
00080                 
00081                 /* remove first item from list, then free the rest of the list and return the stored one */
00082                 BLI_remlink(&anim_data, ale);
00083                 BLI_freelistN(&anim_data);
00084                 
00085                 return ale;
00086         }
00087         
00088         /* no active F-Curve */
00089         return NULL;
00090 }
00091 
00092 /* ************************************************************** */
00093 /* Operator Polling Callbacks */
00094 
00095 /* Check if there are any visible keyframes (for selection tools) */
00096 int graphop_visible_keyframes_poll (bContext *C)
00097 {
00098         bAnimContext ac;
00099         bAnimListElem *ale;
00100         ListBase anim_data = {NULL, NULL};
00101         ScrArea *sa= CTX_wm_area(C);
00102         int filter, items;
00103         short found = 0;
00104         
00105         /* firstly, check if in Graph Editor */
00106         // TODO: also check for region?
00107         if ((sa == NULL) || (sa->spacetype != SPACE_IPO))
00108                 return 0;
00109                 
00110         /* try to init Anim-Context stuff ourselves and check */
00111         if (ANIM_animdata_get_context(C, &ac) == 0)
00112                 return 0;
00113         
00114         /* loop over the visible (selection doesn't matter) F-Curves, and see if they're suitable
00115          * stopping on the first successful match
00116          */
00117         filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
00118         items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
00119         if (items == 0) 
00120                 return 0;
00121         
00122         for (ale = anim_data.first; ale; ale= ale->next) {
00123                 FCurve *fcu= (FCurve *)ale->data;
00124                 
00125                 /* visible curves for selection must fulfull the following criteria:
00126                  *      - it has bezier keyframes
00127                  *      - F-Curve modifiers do not interfere with the result too much 
00128                  *        (i.e. the modifier-control drawing check returns false)
00129                  */
00130                 if (fcu->bezt == NULL)
00131                         continue;
00132                 if (fcurve_are_keyframes_usable(fcu)) {
00133                         found = 1;
00134                         break;
00135                 }
00136         }
00137         
00138         /* cleanup and return findings */
00139         BLI_freelistN(&anim_data);
00140         return found;
00141 }
00142 
00143 /* Check if there are any visible + editable keyframes (for editing tools) */
00144 int graphop_editable_keyframes_poll (bContext *C)
00145 {
00146         bAnimContext ac;
00147         bAnimListElem *ale;
00148         ListBase anim_data = {NULL, NULL};
00149         ScrArea *sa= CTX_wm_area(C);
00150         int filter, items;
00151         short found = 0;
00152         
00153         /* firstly, check if in Graph Editor */
00154         // TODO: also check for region?
00155         if ((sa == NULL) || (sa->spacetype != SPACE_IPO))
00156                 return 0;
00157                 
00158         /* try to init Anim-Context stuff ourselves and check */
00159         if (ANIM_animdata_get_context(C, &ac) == 0)
00160                 return 0;
00161         
00162         /* loop over the editable F-Curves, and see if they're suitable
00163          * stopping on the first successful match
00164          */
00165         filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
00166         items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
00167         if (items == 0) 
00168                 return 0;
00169         
00170         for (ale = anim_data.first; ale; ale= ale->next) {
00171                 FCurve *fcu= (FCurve *)ale->data;
00172                 
00173                 /* editable curves must fulfull the following criteria:
00174                  *      - it has bezier keyframes
00175                  *      - it must not be protected from editing (this is already checked for with the foredit flag
00176                  *      - F-Curve modifiers do not interfere with the result too much 
00177                  *        (i.e. the modifier-control drawing check returns false)
00178                  */
00179                 if (fcu->bezt == NULL)
00180                         continue;
00181                 if (fcurve_is_keyframable(fcu)) {
00182                         found = 1;
00183                         break;
00184                 }
00185         }
00186         
00187         /* cleanup and return findings */
00188         BLI_freelistN(&anim_data);
00189         return found;
00190 }
00191 
00192 /* has active F-Curve that's editable */
00193 int graphop_active_fcurve_poll (bContext *C)
00194 {
00195         bAnimContext ac;
00196         bAnimListElem *ale;
00197         ScrArea *sa= CTX_wm_area(C);
00198         short has_fcurve= 0;
00199         
00200         /* firstly, check if in Graph Editor */
00201         // TODO: also check for region?
00202         if ((sa == NULL) || (sa->spacetype != SPACE_IPO))
00203                 return 0;
00204                 
00205         /* try to init Anim-Context stuff ourselves and check */
00206         if (ANIM_animdata_get_context(C, &ac) == 0)
00207                 return 0;
00208                 
00209         /* try to get the Active F-Curve */
00210         ale= get_active_fcurve_channel(&ac);
00211         if (ale == NULL)
00212                 return 0;
00213                 
00214         /* free temp data... */
00215         has_fcurve= ((ale->data) && (ale->type == ANIMTYPE_FCURVE));
00216         if(has_fcurve) {
00217                 FCurve *fcu= (FCurve *)ale->data;
00218                 has_fcurve= (fcu->flag & FCURVE_VISIBLE)!=0;
00219         }
00220         
00221         MEM_freeN(ale);
00222         
00223         /* return success */
00224         return has_fcurve;
00225 }
00226 
00227 /* has selected F-Curve that's editable */
00228 int graphop_selected_fcurve_poll (bContext *C)
00229 {
00230         bAnimContext ac;
00231         ListBase anim_data = {NULL, NULL};
00232         ScrArea *sa= CTX_wm_area(C);
00233         int filter, items;
00234         
00235         /* firstly, check if in Graph Editor */
00236         // TODO: also check for region?
00237         if ((sa == NULL) || (sa->spacetype != SPACE_IPO))
00238                 return 0;
00239                 
00240         /* try to init Anim-Context stuff ourselves and check */
00241         if (ANIM_animdata_get_context(C, &ac) == 0)
00242                 return 0;
00243         
00244         /* get the editable + selected F-Curves, and as long as we got some, we can return */
00245         filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
00246         items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
00247         if (items == 0) 
00248                 return 0;
00249         
00250         /* cleanup and return findings */
00251         BLI_freelistN(&anim_data);
00252         return 1;
00253 }
00254 
00255 /* ************************************************************** */