|
Blender
V2.59
|
00001 /* 00002 * $Id: anim_filter.c 36545 2011-05-08 05:41:57Z aligorith $ 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) 2008 Blender Foundation, Joshua Leung 00021 * All rights reserved. 00022 * 00023 * 00024 * Contributor(s): Joshua Leung (original author) 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 /* This file contains a system used to provide a layer of abstraction between sources 00035 * of animation data and tools in Animation Editors. The method used here involves 00036 * generating a list of edit structures which enable tools to naively perform the actions 00037 * they require without all the boiler-plate associated with loops within loops and checking 00038 * for cases to ignore. 00039 * 00040 * While this is primarily used for the Action/Dopesheet Editor (and its accessory modes), 00041 * the Graph Editor also uses this for its channel list and for determining which curves 00042 * are being edited. Likewise, the NLA Editor also uses this for its channel list and in 00043 * its operators. 00044 * 00045 * Note: much of the original system this was based on was built before the creation of the RNA 00046 * system. In future, it would be interesting to replace some parts of this code with RNA queries, 00047 * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this 00048 * system, so if any such work does occur, it should only be used for the internals used here... 00049 * 00050 * -- Joshua Leung, Dec 2008 (Last revision July 2009) 00051 */ 00052 00053 #include <string.h> 00054 00055 #include "DNA_anim_types.h" 00056 #include "DNA_armature_types.h" 00057 #include "DNA_camera_types.h" 00058 #include "DNA_lamp_types.h" 00059 #include "DNA_lattice_types.h" 00060 #include "DNA_key_types.h" 00061 #include "DNA_material_types.h" 00062 #include "DNA_mesh_types.h" 00063 #include "DNA_meta_types.h" 00064 #include "DNA_node_types.h" 00065 #include "DNA_particle_types.h" 00066 #include "DNA_space_types.h" 00067 #include "DNA_sequence_types.h" 00068 #include "DNA_scene_types.h" 00069 #include "DNA_screen_types.h" 00070 #include "DNA_world_types.h" 00071 #include "DNA_gpencil_types.h" 00072 #include "DNA_object_types.h" 00073 00074 #include "MEM_guardedalloc.h" 00075 00076 #include "BLI_blenlib.h" 00077 #include "BLI_utildefines.h" 00078 #include "BLI_ghash.h" 00079 00080 #include "BKE_animsys.h" 00081 #include "BKE_action.h" 00082 #include "BKE_fcurve.h" 00083 #include "BKE_context.h" 00084 #include "BKE_global.h" 00085 #include "BKE_group.h" 00086 #include "BKE_key.h" 00087 #include "BKE_main.h" 00088 #include "BKE_material.h" 00089 #include "BKE_node.h" 00090 #include "BKE_sequencer.h" 00091 #include "BKE_utildefines.h" 00092 00093 #include "ED_anim_api.h" 00094 #include "ED_markers.h" 00095 00096 /* ************************************************************ */ 00097 /* Blender Context <-> Animation Context mapping */ 00098 00099 /* ----------- Private Stuff - Action Editor ------------- */ 00100 00101 /* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */ 00102 /* Note: there's a similar function in key.c (ob_get_key) */ 00103 static Key *actedit_get_shapekeys (bAnimContext *ac) 00104 { 00105 Scene *scene= ac->scene; 00106 Object *ob; 00107 Key *key; 00108 00109 ob = OBACT; 00110 if (ob == NULL) 00111 return NULL; 00112 00113 /* XXX pinning is not available in 'ShapeKey' mode... */ 00114 //if (saction->pin) return NULL; 00115 00116 /* shapekey data is stored with geometry data */ 00117 key= ob_get_key(ob); 00118 00119 if (key) { 00120 if (key->type == KEY_RELATIVE) 00121 return key; 00122 } 00123 00124 return NULL; 00125 } 00126 00127 /* Get data being edited in Action Editor (depending on current 'mode') */ 00128 static short actedit_get_context (bAnimContext *ac, SpaceAction *saction) 00129 { 00130 /* sync settings with current view status, then return appropriate data */ 00131 switch (saction->mode) { 00132 case SACTCONT_ACTION: /* 'Action Editor' */ 00133 /* if not pinned, sync with active object */ 00134 if (/*saction->pin == 0*/1) { 00135 if (ac->obact && ac->obact->adt) 00136 saction->action = ac->obact->adt->action; 00137 else 00138 saction->action= NULL; 00139 } 00140 00141 ac->datatype= ANIMCONT_ACTION; 00142 ac->data= saction->action; 00143 00144 ac->mode= saction->mode; 00145 return 1; 00146 00147 case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */ 00148 ac->datatype= ANIMCONT_SHAPEKEY; 00149 ac->data= actedit_get_shapekeys(ac); 00150 00151 ac->mode= saction->mode; 00152 return 1; 00153 00154 case SACTCONT_GPENCIL: /* Grease Pencil */ // XXX review how this mode is handled... 00155 /* update scene-pointer (no need to check for pinning yet, as not implemented) */ 00156 saction->ads.source= (ID *)ac->scene; 00157 00158 ac->datatype= ANIMCONT_GPENCIL; 00159 ac->data= &saction->ads; 00160 00161 ac->mode= saction->mode; 00162 return 1; 00163 00164 case SACTCONT_DOPESHEET: /* DopeSheet */ 00165 /* update scene-pointer (no need to check for pinning yet, as not implemented) */ 00166 saction->ads.source= (ID *)ac->scene; 00167 00168 ac->datatype= ANIMCONT_DOPESHEET; 00169 ac->data= &saction->ads; 00170 00171 ac->mode= saction->mode; 00172 return 1; 00173 00174 default: /* unhandled yet */ 00175 ac->datatype= ANIMCONT_NONE; 00176 ac->data= NULL; 00177 00178 ac->mode= -1; 00179 return 0; 00180 } 00181 } 00182 00183 /* ----------- Private Stuff - Graph Editor ------------- */ 00184 00185 /* Get data being edited in Graph Editor (depending on current 'mode') */ 00186 static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo) 00187 { 00188 /* init dopesheet data if non-existant (i.e. for old files) */ 00189 if (sipo->ads == NULL) { 00190 sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet"); 00191 sipo->ads->source= (ID *)ac->scene; 00192 } 00193 00194 /* set settings for Graph Editor - "Selected = Editable" */ 00195 if (sipo->flag & SIPO_SELCUVERTSONLY) 00196 sipo->ads->filterflag |= ADS_FILTER_SELEDIT; 00197 else 00198 sipo->ads->filterflag &= ~ADS_FILTER_SELEDIT; 00199 00200 /* sync settings with current view status, then return appropriate data */ 00201 switch (sipo->mode) { 00202 case SIPO_MODE_ANIMATION: /* Animation F-Curve Editor */ 00203 /* update scene-pointer (no need to check for pinning yet, as not implemented) */ 00204 sipo->ads->source= (ID *)ac->scene; 00205 sipo->ads->filterflag &= ~ADS_FILTER_ONLYDRIVERS; 00206 00207 ac->datatype= ANIMCONT_FCURVES; 00208 ac->data= sipo->ads; 00209 00210 ac->mode= sipo->mode; 00211 return 1; 00212 00213 case SIPO_MODE_DRIVERS: /* Driver F-Curve Editor */ 00214 /* update scene-pointer (no need to check for pinning yet, as not implemented) */ 00215 sipo->ads->source= (ID *)ac->scene; 00216 sipo->ads->filterflag |= ADS_FILTER_ONLYDRIVERS; 00217 00218 ac->datatype= ANIMCONT_DRIVERS; 00219 ac->data= sipo->ads; 00220 00221 ac->mode= sipo->mode; 00222 return 1; 00223 00224 default: /* unhandled yet */ 00225 ac->datatype= ANIMCONT_NONE; 00226 ac->data= NULL; 00227 00228 ac->mode= -1; 00229 return 0; 00230 } 00231 } 00232 00233 /* ----------- Private Stuff - NLA Editor ------------- */ 00234 00235 /* Get data being edited in Graph Editor (depending on current 'mode') */ 00236 static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla) 00237 { 00238 /* init dopesheet data if non-existant (i.e. for old files) */ 00239 if (snla->ads == NULL) 00240 snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet"); 00241 00242 /* sync settings with current view status, then return appropriate data */ 00243 /* update scene-pointer (no need to check for pinning yet, as not implemented) */ 00244 snla->ads->source= (ID *)ac->scene; 00245 snla->ads->filterflag |= ADS_FILTER_ONLYNLA; 00246 00247 ac->datatype= ANIMCONT_NLA; 00248 ac->data= snla->ads; 00249 00250 return 1; 00251 } 00252 00253 /* ----------- Public API --------------- */ 00254 00255 /* Obtain current anim-data context, given that context info from Blender context has already been set 00256 * - AnimContext to write to is provided as pointer to var on stack so that we don't have 00257 * allocation/freeing costs (which are not that avoidable with channels). 00258 */ 00259 short ANIM_animdata_context_getdata (bAnimContext *ac) 00260 { 00261 ScrArea *sa= ac->sa; 00262 short ok= 0; 00263 00264 /* context depends on editor we are currently in */ 00265 if (sa) { 00266 switch (sa->spacetype) { 00267 case SPACE_ACTION: 00268 { 00269 SpaceAction *saction= (SpaceAction *)sa->spacedata.first; 00270 ok= actedit_get_context(ac, saction); 00271 } 00272 break; 00273 00274 case SPACE_IPO: 00275 { 00276 SpaceIpo *sipo= (SpaceIpo *)sa->spacedata.first; 00277 ok= graphedit_get_context(ac, sipo); 00278 } 00279 break; 00280 00281 case SPACE_NLA: 00282 { 00283 SpaceNla *snla= (SpaceNla *)sa->spacedata.first; 00284 ok= nlaedit_get_context(ac, snla); 00285 } 00286 break; 00287 } 00288 } 00289 00290 /* check if there's any valid data */ 00291 if (ok && ac->data) 00292 return 1; 00293 else 00294 return 0; 00295 } 00296 00297 /* Obtain current anim-data context from Blender Context info 00298 * - AnimContext to write to is provided as pointer to var on stack so that we don't have 00299 * allocation/freeing costs (which are not that avoidable with channels). 00300 * - Clears data and sets the information from Blender Context which is useful 00301 */ 00302 short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac) 00303 { 00304 ScrArea *sa= CTX_wm_area(C); 00305 ARegion *ar= CTX_wm_region(C); 00306 Scene *scene= CTX_data_scene(C); 00307 00308 /* clear old context info */ 00309 if (ac == NULL) return 0; 00310 memset(ac, 0, sizeof(bAnimContext)); 00311 00312 /* get useful default context settings from context */ 00313 ac->scene= scene; 00314 if (scene) { 00315 ac->markers= ED_context_get_markers(C); 00316 ac->obact= (scene->basact)? scene->basact->object : NULL; 00317 } 00318 ac->sa= sa; 00319 ac->ar= ar; 00320 ac->spacetype= (sa) ? sa->spacetype : 0; 00321 ac->regiontype= (ar) ? ar->regiontype : 0; 00322 00323 /* get data context info */ 00324 return ANIM_animdata_context_getdata(ac); 00325 } 00326 00327 /* ************************************************************ */ 00328 /* Blender Data <-- Filter --> Channels to be operated on */ 00329 00330 /* quick macro to test if AnimData is usable */ 00331 #define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action) 00332 00333 /* quick macro to test if AnimData is usable for drivers */ 00334 #define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first) 00335 00336 /* quick macro to test if AnimData is usable for NLA */ 00337 #define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first) 00338 00339 00340 /* Quick macro to test for all three avove usability tests, performing the appropriate provided 00341 * action for each when the AnimData context is appropriate. 00342 * 00343 * Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes. 00344 * 00345 * For this to work correctly, a standard set of data needs to be available within the scope that this 00346 * gets called in: 00347 * - ListBase anim_data; 00348 * - bDopeSheet *ads; 00349 * - bAnimListElem *ale; 00350 * - int items; 00351 * 00352 * - id: ID block which should have an AnimData pointer following it immediately, to use 00353 * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA) 00354 * - nlaOk: line or block of code to execute for NLA tracks+strips case 00355 * - driversOk: line or block of code to execute for Drivers case 00356 * - keysOk: line or block of code for Keyframes case 00357 * 00358 * The checks for the various cases are as follows: 00359 * 0) top level: checks for animdata and also that all the F-Curves for the block will be visible 00360 * 1) animdata check: for filtering animdata blocks only 00361 * 2A) nla tracks: include animdata block's data as there are NLA tracks+strips there 00362 * 2B) actions to convert to nla: include animdata block's data as there is an action that can be 00363 * converted to a new NLA strip, and the filtering options allow this 00364 * 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor) 00365 * 4) normal keyframes: only when there is an active action 00366 */ 00367 #define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \ 00368 {\ 00369 if ((id)->adt) {\ 00370 if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) {\ 00371 if (filter_mode & ANIMFILTER_ANIMDATA) {\ 00372 adtOk\ 00373 }\ 00374 else if (ads->filterflag & ADS_FILTER_ONLYNLA) {\ 00375 if (ANIMDATA_HAS_NLA(id)) {\ 00376 nlaOk\ 00377 }\ 00378 else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) {\ 00379 nlaOk\ 00380 }\ 00381 }\ 00382 else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) {\ 00383 if (ANIMDATA_HAS_DRIVERS(id)) {\ 00384 driversOk\ 00385 }\ 00386 }\ 00387 else {\ 00388 if (ANIMDATA_HAS_KEYS(id)) {\ 00389 keysOk\ 00390 }\ 00391 }\ 00392 }\ 00393 }\ 00394 } 00395 00396 00397 /* quick macro to add a pointer to an AnimData block as a channel */ 00398 #define ANIMDATA_ADD_ANIMDATA(id) \ 00399 {\ 00400 ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\ 00401 if (ale) {\ 00402 BLI_addtail(anim_data, ale);\ 00403 items++;\ 00404 }\ 00405 } 00406 00407 /* quick macro to test if an anim-channel representing an AnimData block is suitably active */ 00408 #define ANIMCHANNEL_ACTIVEOK(ale) \ 00409 ( !(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE) ) 00410 00411 /* quick macro to test if an anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */ 00412 #define ANIMCHANNEL_SELOK(test_func) \ 00413 ( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \ 00414 ((filter_mode & ANIMFILTER_SEL) && test_func) || \ 00415 ((filter_mode & ANIMFILTER_UNSEL) && test_func==0) ) 00416 00417 /* quick macro to test if an anim-channel (F-Curve) is selected ok for editing purposes 00418 * - _SELEDIT means that only selected curves will have visible+editable keyframes 00419 * 00420 * checks here work as follows: 00421 * 1) seledit off - don't need to consider the implications of this option 00422 * 2) foredit off - we're not considering editing, so channel is ok still 00423 * 3) test_func (i.e. selection test) - only if selected, this test will pass 00424 */ 00425 #define ANIMCHANNEL_SELEDITOK(test_func) \ 00426 ( !(filter_mode & ANIMFILTER_SELEDIT) || \ 00427 !(filter_mode & ANIMFILTER_FOREDIT) || \ 00428 (test_func) ) 00429 00430 /* ----------- 'Private' Stuff --------------- */ 00431 00432 /* this function allocates memory for a new bAnimListElem struct for the 00433 * provided animation channel-data. 00434 */ 00435 static bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype, ID *owner_id) 00436 { 00437 bAnimListElem *ale= NULL; 00438 00439 /* only allocate memory if there is data to convert */ 00440 if (data) { 00441 /* allocate and set generic data */ 00442 ale= MEM_callocN(sizeof(bAnimListElem), "bAnimListElem"); 00443 00444 ale->data= data; 00445 ale->type= datatype; 00446 // XXX what is the point of the owner data? 00447 // xxx try and use this to simplify the problem of finding whether parent channels are working... 00448 ale->owner= owner; 00449 ale->ownertype= ownertype; 00450 00451 ale->id= owner_id; 00452 ale->adt= BKE_animdata_from_id(owner_id); 00453 00454 /* do specifics */ 00455 switch (datatype) { 00456 case ANIMTYPE_SUMMARY: 00457 { 00458 /* nothing to include for now... this is just a dummy wrappy around all the other channels 00459 * in the DopeSheet, and gets included at the start of the list 00460 */ 00461 ale->key_data= NULL; 00462 ale->datatype= ALE_ALL; 00463 } 00464 break; 00465 00466 case ANIMTYPE_SCENE: 00467 { 00468 Scene *sce= (Scene *)data; 00469 00470 ale->flag= sce->flag; 00471 00472 ale->key_data= sce; 00473 ale->datatype= ALE_SCE; 00474 00475 ale->adt= BKE_animdata_from_id(data); 00476 } 00477 break; 00478 case ANIMTYPE_OBJECT: 00479 { 00480 Base *base= (Base *)data; 00481 Object *ob= base->object; 00482 00483 ale->flag= ob->flag; 00484 00485 ale->key_data= ob; 00486 ale->datatype= ALE_OB; 00487 00488 ale->adt= BKE_animdata_from_id(&ob->id); 00489 } 00490 break; 00491 case ANIMTYPE_FILLACTD: 00492 { 00493 bAction *act= (bAction *)data; 00494 00495 ale->flag= act->flag; 00496 00497 ale->key_data= act; 00498 ale->datatype= ALE_ACT; 00499 } 00500 break; 00501 case ANIMTYPE_FILLDRIVERS: 00502 { 00503 AnimData *adt= (AnimData *)data; 00504 00505 ale->flag= adt->flag; 00506 00507 // XXX... drivers don't show summary for now 00508 ale->key_data= NULL; 00509 ale->datatype= ALE_NONE; 00510 } 00511 break; 00512 case ANIMTYPE_FILLMATD: 00513 { 00514 Object *ob= (Object *)data; 00515 00516 ale->flag= FILTER_MAT_OBJC(ob); 00517 00518 ale->key_data= NULL; 00519 ale->datatype= ALE_NONE; 00520 } 00521 break; 00522 case ANIMTYPE_FILLPARTD: 00523 { 00524 Object *ob= (Object *)data; 00525 00526 ale->flag= FILTER_PART_OBJC(ob); 00527 00528 ale->key_data= NULL; 00529 ale->datatype= ALE_NONE; 00530 } 00531 break; 00532 case ANIMTYPE_FILLTEXD: 00533 { 00534 ID *id= (ID *)data; 00535 00536 switch (GS(id->name)) { 00537 case ID_MA: 00538 { 00539 Material *ma= (Material *)id; 00540 ale->flag= FILTER_TEX_MATC(ma); 00541 } 00542 break; 00543 case ID_LA: 00544 { 00545 Lamp *la= (Lamp *)id; 00546 ale->flag= FILTER_TEX_LAMC(la); 00547 } 00548 break; 00549 case ID_WO: 00550 { 00551 World *wo= (World *)id; 00552 ale->flag= FILTER_TEX_WORC(wo); 00553 } 00554 break; 00555 } 00556 00557 ale->key_data= NULL; 00558 ale->datatype= ALE_NONE; 00559 } 00560 break; 00561 00562 case ANIMTYPE_DSMAT: 00563 { 00564 Material *ma= (Material *)data; 00565 AnimData *adt= ma->adt; 00566 00567 ale->flag= FILTER_MAT_OBJD(ma); 00568 00569 ale->key_data= (adt) ? adt->action : NULL; 00570 ale->datatype= ALE_ACT; 00571 00572 ale->adt= BKE_animdata_from_id(data); 00573 } 00574 break; 00575 case ANIMTYPE_DSLAM: 00576 { 00577 Lamp *la= (Lamp *)data; 00578 AnimData *adt= la->adt; 00579 00580 ale->flag= FILTER_LAM_OBJD(la); 00581 00582 ale->key_data= (adt) ? adt->action : NULL; 00583 ale->datatype= ALE_ACT; 00584 00585 ale->adt= BKE_animdata_from_id(data); 00586 } 00587 break; 00588 case ANIMTYPE_DSCAM: 00589 { 00590 Camera *ca= (Camera *)data; 00591 AnimData *adt= ca->adt; 00592 00593 ale->flag= FILTER_CAM_OBJD(ca); 00594 00595 ale->key_data= (adt) ? adt->action : NULL; 00596 ale->datatype= ALE_ACT; 00597 00598 ale->adt= BKE_animdata_from_id(data); 00599 } 00600 break; 00601 case ANIMTYPE_DSCUR: 00602 { 00603 Curve *cu= (Curve *)data; 00604 AnimData *adt= cu->adt; 00605 00606 ale->flag= FILTER_CUR_OBJD(cu); 00607 00608 ale->key_data= (adt) ? adt->action : NULL; 00609 ale->datatype= ALE_ACT; 00610 00611 ale->adt= BKE_animdata_from_id(data); 00612 } 00613 break; 00614 case ANIMTYPE_DSARM: 00615 { 00616 bArmature *arm= (bArmature *)data; 00617 AnimData *adt= arm->adt; 00618 00619 ale->flag= FILTER_ARM_OBJD(arm); 00620 00621 ale->key_data= (adt) ? adt->action : NULL; 00622 ale->datatype= ALE_ACT; 00623 00624 ale->adt= BKE_animdata_from_id(data); 00625 } 00626 break; 00627 case ANIMTYPE_DSMESH: 00628 { 00629 Mesh *me= (Mesh *)data; 00630 AnimData *adt= me->adt; 00631 00632 ale->flag= FILTER_MESH_OBJD(me); 00633 00634 ale->key_data= (adt) ? adt->action : NULL; 00635 ale->datatype= ALE_ACT; 00636 00637 ale->adt= BKE_animdata_from_id(data); 00638 } 00639 break; 00640 case ANIMTYPE_DSLAT: 00641 { 00642 Lattice *lt= (Lattice *)data; 00643 AnimData *adt= lt->adt; 00644 00645 ale->flag= FILTER_LATTICE_OBJD(lt); 00646 00647 ale->key_data= (adt) ? adt->action : NULL; 00648 ale->datatype= ALE_ACT; 00649 00650 ale->adt= BKE_animdata_from_id(data); 00651 } 00652 break; 00653 case ANIMTYPE_DSSKEY: 00654 { 00655 Key *key= (Key *)data; 00656 AnimData *adt= key->adt; 00657 00658 ale->flag= FILTER_SKE_OBJD(key); 00659 00660 ale->key_data= (adt) ? adt->action : NULL; 00661 ale->datatype= ALE_ACT; 00662 00663 ale->adt= BKE_animdata_from_id(data); 00664 } 00665 break; 00666 case ANIMTYPE_DSWOR: 00667 { 00668 World *wo= (World *)data; 00669 AnimData *adt= wo->adt; 00670 00671 ale->flag= FILTER_WOR_SCED(wo); 00672 00673 ale->key_data= (adt) ? adt->action : NULL; 00674 ale->datatype= ALE_ACT; 00675 00676 ale->adt= BKE_animdata_from_id(data); 00677 } 00678 break; 00679 case ANIMTYPE_DSNTREE: 00680 { 00681 bNodeTree *ntree= (bNodeTree *)data; 00682 AnimData *adt= ntree->adt; 00683 00684 ale->flag= FILTER_NTREE_SCED(ntree); 00685 00686 ale->key_data= (adt) ? adt->action : NULL; 00687 ale->datatype= ALE_ACT; 00688 00689 ale->adt= BKE_animdata_from_id(data); 00690 } 00691 break; 00692 case ANIMTYPE_DSPART: 00693 { 00694 ParticleSettings *part= (ParticleSettings*)ale->data; 00695 AnimData *adt= part->adt; 00696 00697 ale->flag= FILTER_PART_OBJD(part); 00698 00699 ale->key_data= (adt) ? adt->action : NULL; 00700 ale->datatype= ALE_ACT; 00701 00702 ale->adt= BKE_animdata_from_id(data); 00703 } 00704 break; 00705 case ANIMTYPE_DSTEX: 00706 { 00707 Tex *tex= (Tex *)data; 00708 AnimData *adt= tex->adt; 00709 00710 ale->flag= FILTER_TEX_DATA(tex); 00711 00712 ale->key_data= (adt) ? adt->action : NULL; 00713 ale->datatype= ALE_ACT; 00714 00715 ale->adt= BKE_animdata_from_id(data); 00716 } 00717 break; 00718 00719 case ANIMTYPE_GROUP: 00720 { 00721 bActionGroup *agrp= (bActionGroup *)data; 00722 00723 ale->flag= agrp->flag; 00724 00725 ale->key_data= NULL; 00726 ale->datatype= ALE_GROUP; 00727 } 00728 break; 00729 case ANIMTYPE_FCURVE: 00730 { 00731 FCurve *fcu= (FCurve *)data; 00732 00733 ale->flag= fcu->flag; 00734 00735 ale->key_data= fcu; 00736 ale->datatype= ALE_FCURVE; 00737 } 00738 break; 00739 00740 case ANIMTYPE_SHAPEKEY: 00741 { 00742 KeyBlock *kb= (KeyBlock *)data; 00743 Key *key= (Key *)ale->id; 00744 00745 ale->flag= kb->flag; 00746 00747 /* whether we have keyframes depends on whether there is a Key block to find it from */ 00748 if (key) { 00749 /* index of shapekey is defined by place in key's list */ 00750 ale->index= BLI_findindex(&key->block, kb); 00751 00752 /* the corresponding keyframes are from the animdata */ 00753 if (ale->adt && ale->adt->action) { 00754 bAction *act= ale->adt->action; 00755 char *rna_path = key_get_curValue_rnaPath(key, kb); 00756 00757 /* try to find the F-Curve which corresponds to this exactly, 00758 * then free the MEM_alloc'd string 00759 */ 00760 if (rna_path) { 00761 ale->key_data= (void *)list_find_fcurve(&act->curves, rna_path, 0); 00762 MEM_freeN(rna_path); 00763 } 00764 } 00765 ale->datatype= (ale->key_data)? ALE_FCURVE : ALE_NONE; 00766 } 00767 } 00768 break; 00769 00770 case ANIMTYPE_GPLAYER: 00771 { 00772 bGPDlayer *gpl= (bGPDlayer *)data; 00773 00774 ale->flag= gpl->flag; 00775 00776 ale->key_data= NULL; 00777 ale->datatype= ALE_GPFRAME; 00778 } 00779 break; 00780 00781 case ANIMTYPE_NLATRACK: 00782 { 00783 NlaTrack *nlt= (NlaTrack *)data; 00784 00785 ale->flag= nlt->flag; 00786 00787 ale->key_data= &nlt->strips; 00788 ale->datatype= ALE_NLASTRIP; 00789 } 00790 break; 00791 case ANIMTYPE_NLAACTION: 00792 { 00793 /* nothing to include for now... nothing editable from NLA-perspective here */ 00794 ale->key_data= NULL; 00795 ale->datatype= ALE_NONE; 00796 } 00797 break; 00798 } 00799 } 00800 00801 /* return created datatype */ 00802 return ale; 00803 } 00804 00805 /* ----------------------------------------- */ 00806 00807 /* 'Only Selected' selected data filtering 00808 * NOTE: when this function returns true, the F-Curve is to be skipped 00809 */ 00810 static int skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode) 00811 { 00812 if (GS(owner_id->name) == ID_OB) { 00813 Object *ob= (Object *)owner_id; 00814 00815 /* only consider if F-Curve involves pose.bones */ 00816 if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) { 00817 bPoseChannel *pchan; 00818 char *bone_name; 00819 00820 /* get bone-name, and check if this bone is selected */ 00821 bone_name= BLI_getQuotedStr(fcu->rna_path, "pose.bones["); 00822 pchan= get_pose_channel(ob->pose, bone_name); 00823 if (bone_name) MEM_freeN(bone_name); 00824 00825 /* check whether to continue or skip */ 00826 if ((pchan) && (pchan->bone)) { 00827 /* if only visible channels, skip if bone not visible unless user wants channels from hidden data too */ 00828 if ((filter_mode & ANIMFILTER_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { 00829 bArmature *arm= (bArmature *)ob->data; 00830 00831 if ((arm->layer & pchan->bone->layer) == 0) 00832 return 1; 00833 } 00834 00835 /* can only add this F-Curve if it is selected */ 00836 if ((pchan->bone->flag & BONE_SELECTED) == 0) 00837 return 1; 00838 } 00839 } 00840 } 00841 else if (GS(owner_id->name) == ID_SCE) { 00842 Scene *scene = (Scene *)owner_id; 00843 00844 /* only consider if F-Curve involves sequence_editor.sequences */ 00845 if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { 00846 Editing *ed= seq_give_editing(scene, FALSE); 00847 Sequence *seq; 00848 char *seq_name; 00849 00850 /* get strip name, and check if this strip is selected */ 00851 seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all["); 00852 seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE); 00853 if (seq_name) MEM_freeN(seq_name); 00854 00855 /* can only add this F-Curve if it is selected */ 00856 if (seq==NULL || (seq->flag & SELECT)==0) 00857 return 1; 00858 } 00859 } 00860 else if (GS(owner_id->name) == ID_NT) { 00861 bNodeTree *ntree = (bNodeTree *)owner_id; 00862 00863 /* check for selected nodes */ 00864 if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) { 00865 bNode *node; 00866 char *node_name; 00867 00868 /* get strip name, and check if this strip is selected */ 00869 node_name= BLI_getQuotedStr(fcu->rna_path, "nodes["); 00870 node = nodeFindNodebyName(ntree, node_name); 00871 if (node_name) MEM_freeN(node_name); 00872 00873 /* can only add this F-Curve if it is selected */ 00874 if ((node) && (node->flag & NODE_SELECT)==0) 00875 return 1; 00876 } 00877 } 00878 return 0; 00879 } 00880 00881 /* (Display-)Name-based F-Curve filtering 00882 * NOTE: when this function returns true, the F-Curve is to be skipped 00883 */ 00884 static short skip_fcurve_with_name (bDopeSheet *ads, FCurve *fcu, ID *owner_id) 00885 { 00886 bAnimListElem ale_dummy = {0}; 00887 bAnimChannelType *acf; 00888 00889 /* create a dummy wrapper for the F-Curve */ 00890 ale_dummy.type = ANIMTYPE_FCURVE; 00891 ale_dummy.id = owner_id; 00892 ale_dummy.data = fcu; 00893 00894 /* get type info for channel */ 00895 acf = ANIM_channel_get_typeinfo(&ale_dummy); 00896 if (acf && acf->name) { 00897 char name[256]; /* hopefully this will be enough! */ 00898 00899 /* get name */ 00900 acf->name(&ale_dummy, name); 00901 00902 /* check for partial match with the match string, assuming case insensitive filtering 00903 * if match, this channel shouldn't be ignored! 00904 */ 00905 return BLI_strcasestr(name, ads->searchstr) == NULL; 00906 } 00907 00908 /* just let this go... */ 00909 return 1; 00910 } 00911 00912 /* find the next F-Curve that is usable for inclusion */ 00913 static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id) 00914 { 00915 FCurve *fcu = NULL; 00916 00917 /* loop over F-Curves - assume that the caller of this has already checked that these should be included 00918 * NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too... 00919 */ 00920 for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) { 00921 /* special exception for Pose-Channel/Sequence-Strip/Node Based F-Curves: 00922 * - the 'Only Selected' data filter should be applied to Pose-Channel data too, but those are 00923 * represented as F-Curves. The way the filter for objects worked was to be the first check 00924 * after 'normal' visibility, so this is done first here too... 00925 * - we currently use an 'approximate' method for getting these F-Curves that doesn't require 00926 * carefully checking the entire path 00927 * - this will also affect things like Drivers, and also works for Bone Constraints 00928 */ 00929 if ( ((ads) && (ads->filterflag & ADS_FILTER_ONLYSEL)) && (owner_id) ) { 00930 if (skip_fcurve_selected_data(ads, fcu, owner_id, filter_mode)) 00931 continue; 00932 } 00933 00934 /* only include if visible (Graph Editor check, not channels check) */ 00935 if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) { 00936 /* only work with this channel and its subchannels if it is editable */ 00937 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) { 00938 /* only include this curve if selected in a way consistent with the filtering requirements */ 00939 if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu)) ) { 00940 /* only include if this curve is active */ 00941 if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) { 00942 /* name based filtering... */ 00943 if ( ((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id) ) { 00944 if (skip_fcurve_with_name(ads, fcu, owner_id)) 00945 continue; 00946 } 00947 00948 /* this F-Curve can be used, so return it */ 00949 return fcu; 00950 } 00951 } 00952 } 00953 } 00954 } 00955 00956 /* no (more) F-Curves from the list are suitable... */ 00957 return NULL; 00958 } 00959 00960 static int animdata_filter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, void *owner, short ownertype, int filter_mode, ID *owner_id) 00961 { 00962 FCurve *fcu; 00963 int items = 0; 00964 00965 /* loop over every F-Curve able to be included 00966 * - this for-loop works like this: 00967 * 1) the starting F-Curve is assigned to the fcu pointer so that we have a starting point to search from 00968 * 2) the first valid F-Curve to start from (which may include the one given as 'first') in the remaining 00969 * list of F-Curves is found, and verified to be non-null 00970 * 3) the F-Curve referenced by fcu pointer is added to the list 00971 * 4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through 00972 * the rest of the F-Curve list without an eternal loop. Back to step 2 :) 00973 */ 00974 for (fcu=first; ( (fcu = animdata_filter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu=fcu->next) 00975 { 00976 bAnimListElem *ale = make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id); 00977 00978 if (ale) { 00979 BLI_addtail(anim_data, ale); 00980 items++; 00981 } 00982 } 00983 00984 /* return the number of items added to the list */ 00985 return items; 00986 } 00987 00988 static int animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, void *owner, short ownertype, ID *owner_id) 00989 { 00990 bAnimListElem *ale=NULL; 00991 bActionGroup *agrp; 00992 FCurve *lastchan=NULL; 00993 int items = 0; 00994 00995 /* don't include anything from this action if it is linked in from another file, 00996 * and we're getting stuff for editing... 00997 */ 00998 // TODO: need a way of tagging other channels that may also be affected... 00999 if ((filter_mode & ANIMFILTER_FOREDIT) && (act->id.lib)) 01000 return 0; 01001 01002 /* loop over groups */ 01003 // TODO: in future, should we expect to need nested groups? 01004 for (agrp= act->groups.first; agrp; agrp= agrp->next) { 01005 FCurve *first_fcu; 01006 int filter_gmode; 01007 01008 /* store reference to last channel of group */ 01009 if (agrp->channels.last) 01010 lastchan= agrp->channels.last; 01011 01012 01013 /* make a copy of filtering flags for use by the sub-channels of this group */ 01014 filter_gmode= filter_mode; 01015 01016 /* if we care about the selection status of the channels, 01017 * but the group isn't expanded... 01018 */ 01019 if ( (filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) && /* care about selection status */ 01020 (EXPANDED_AGRP(ac, agrp)==0) ) /* group isn't expanded */ 01021 { 01022 /* if the group itself isn't selected appropriately, we shouldn't consider it's children either */ 01023 if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) == 0) 01024 continue; 01025 01026 /* if we're still here, then the selection status of the curves within this group should not matter, 01027 * since this creates too much overhead for animators (i.e. making a slow workflow) 01028 * 01029 * Tools affected by this at time of coding (2010 Feb 09): 01030 * - inserting keyframes on selected channels only 01031 * - pasting keyframes 01032 * - creating ghost curves in Graph Editor 01033 */ 01034 filter_gmode &= ~(ANIMFILTER_SEL|ANIMFILTER_UNSEL); 01035 } 01036 01037 01038 /* get the first F-Curve in this group we can start to use, and if there isn't any F-Curve to start from, 01039 * then don't use this group at all... 01040 * 01041 * NOTE: use filter_gmode here not filter_mode, since there may be some flags we shouldn't consider under certain circumstances 01042 */ 01043 first_fcu = animdata_filter_fcurve_next(ads, agrp->channels.first, agrp, filter_gmode, owner_id); 01044 01045 /* Bug note: 01046 * Selecting open group to toggle visbility of the group, where the F-Curves of the group are not suitable 01047 * for inclusion due to their selection status (vs visibility status of bones/etc., as is usually the case), 01048 * will not work, since the group gets skipped. However, fixing this can easily reintroduce the bugs whereby 01049 * hidden groups (due to visibility status of bones/etc.) that were selected before becoming invisible, can 01050 * easily get deleted accidentally as they'd be included in the list filtered for that purpose. 01051 * 01052 * So, for now, best solution is to just leave this note here, and hope to find a solution at a later date. 01053 * -- Joshua Leung, 2010 Feb 10 01054 */ 01055 if (first_fcu) { 01056 /* add this group as a channel first */ 01057 if ((filter_mode & ANIMFILTER_CHANNELS) || !(filter_mode & ANIMFILTER_CURVESONLY)) { 01058 /* filter selection of channel specially here again, since may be open and not subject to previous test */ 01059 if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) { 01060 ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE, owner_id); 01061 if (ale) { 01062 BLI_addtail(anim_data, ale); 01063 items++; 01064 } 01065 } 01066 } 01067 01068 /* there are some situations, where only the channels of the action group should get considered */ 01069 if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) { 01070 /* filters here are a bit convoulted... 01071 * - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes 01072 * - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed) 01073 * 01074 * cases when we should include F-Curves inside group: 01075 * - we don't care about visibility 01076 * - group is expanded 01077 * - we just need the F-Curves present 01078 */ 01079 if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(ac, agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) ) 01080 { 01081 /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter, 01082 * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing 01083 * all its sub-curves to be shown 01084 */ 01085 if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) ) 01086 { 01087 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) { 01088 /* NOTE: filter_gmode is used here, not standard filter_mode, since there may be some flags that shouldn't apply */ 01089 items += animdata_filter_fcurves(anim_data, ads, first_fcu, agrp, owner, ownertype, filter_gmode, owner_id); 01090 } 01091 } 01092 } 01093 } 01094 } 01095 } 01096 01097 /* loop over un-grouped F-Curves (only if we're not only considering those channels in the animive group) */ 01098 if (!(filter_mode & ANIMFILTER_ACTGROUPED)) { 01099 // XXX the 'owner' info here needs review... 01100 items += animdata_filter_fcurves(anim_data, ads, (lastchan)?(lastchan->next):(act->curves.first), NULL, owner, ownertype, filter_mode, owner_id); 01101 } 01102 01103 /* return the number of items added to the list */ 01104 return items; 01105 } 01106 01107 /* Include NLA-Data for NLA-Editor: 01108 * - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display 01109 * Although the evaluation order is from the first track to the last and then apply the Action on top, 01110 * we present this in the UI as the Active Action followed by the last track to the first so that we 01111 * get the evaluation order presented as per a stack. 01112 * - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation 01113 * order, i.e. first to last. Otherwise, some tools may get screwed up. 01114 */ 01115 static int animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *UNUSED(ads), AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id) 01116 { 01117 bAnimListElem *ale; 01118 NlaTrack *nlt; 01119 NlaTrack *first=NULL, *next=NULL; 01120 int items = 0; 01121 01122 /* if showing channels, include active action */ 01123 if (filter_mode & ANIMFILTER_CHANNELS) { 01124 /* there isn't really anything editable here, so skip if need editable */ 01125 // TODO: currently, selection isn't checked since it doesn't matter 01126 if ((filter_mode & ANIMFILTER_FOREDIT) == 0) { 01127 /* just add the action track now (this MUST appear for drawing) 01128 * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then 01129 * overwrite this with the real value - REVIEW THIS... 01130 */ 01131 ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id); 01132 ale->data= (adt->action) ? adt->action : NULL; 01133 01134 if (ale) { 01135 BLI_addtail(anim_data, ale); 01136 items++; 01137 } 01138 } 01139 01140 /* first track to include will be the last one if we're filtering by channels */ 01141 first= adt->nla_tracks.last; 01142 } 01143 else { 01144 /* first track to include will the the first one (as per normal) */ 01145 first= adt->nla_tracks.first; 01146 } 01147 01148 /* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */ 01149 for (nlt= first; nlt; nlt= next) { 01150 /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */ 01151 if (filter_mode & ANIMFILTER_CHANNELS) 01152 next= nlt->prev; 01153 else 01154 next= nlt->next; 01155 01156 /* if we're in NLA-tweakmode, don't show this track if it was disabled (due to tweaking) for now 01157 * - active track should still get shown though (even though it has disabled flag set) 01158 */ 01159 // FIXME: the channels after should still get drawn, just 'differently', and after an active-action channel 01160 if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED) && !(nlt->flag & NLATRACK_ACTIVE)) 01161 continue; 01162 01163 /* only work with this channel and its subchannels if it is editable */ 01164 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) { 01165 /* only include this track if selected in a way consistent with the filtering requirements */ 01166 if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) { 01167 /* only include if this track is active */ 01168 if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) { 01169 ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id); 01170 01171 if (ale) { 01172 BLI_addtail(anim_data, ale); 01173 items++; 01174 } 01175 } 01176 } 01177 } 01178 } 01179 01180 /* return the number of items added to the list */ 01181 return items; 01182 } 01183 01184 /* Include ShapeKey Data for ShapeKey Editor */ 01185 static int animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key *key, int filter_mode) 01186 { 01187 bAnimListElem *ale; 01188 int items = 0; 01189 01190 /* check if channels or only F-Curves */ 01191 if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { 01192 KeyBlock *kb; 01193 01194 /* loop through the channels adding ShapeKeys as appropriate */ 01195 for (kb= key->block.first; kb; kb= kb->next) { 01196 /* skip the first one, since that's the non-animateable basis */ 01197 // XXX maybe in future this may become handy? 01198 if (kb == key->block.first) continue; 01199 01200 /* only work with this channel and its subchannels if it is editable */ 01201 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) { 01202 /* only include this track if selected in a way consistent with the filtering requirements */ 01203 if ( ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb)) ) { 01204 // TODO: consider 'active' too? 01205 01206 /* owner-id here must be key so that the F-Curve can be resolved... */ 01207 ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, NULL, ANIMTYPE_NONE, (ID *)key); 01208 01209 if (ale) { 01210 BLI_addtail(anim_data, ale); 01211 items++; 01212 } 01213 } 01214 } 01215 } 01216 } 01217 else { 01218 /* just use the action associated with the shapekey */ 01219 // FIXME: is owner-id and having no owner/dopesheet really fine? 01220 if (key->adt) { 01221 if (filter_mode & ANIMFILTER_ANIMDATA) 01222 ANIMDATA_ADD_ANIMDATA(key) 01223 else if (key->adt->action) 01224 items= animdata_filter_action(ac, anim_data, NULL, key->adt->action, filter_mode, NULL, ANIMTYPE_NONE, (ID *)key); 01225 } 01226 } 01227 01228 /* return the number of items added to the list */ 01229 return items; 01230 } 01231 01232 /* Grab all Grase Pencil datablocks in file */ 01233 // TODO: should this be amalgamated with the dopesheet filtering code? 01234 static int animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data), int filter_mode) 01235 { 01236 bAnimListElem *ale; 01237 bGPdata *gpd; 01238 bGPDlayer *gpl; 01239 int items = 0; 01240 01241 /* check if filtering types are appropriate */ 01242 if (!(filter_mode & (ANIMFILTER_ACTGROUPED|ANIMFILTER_CURVESONLY))) 01243 { 01244 /* for now, grab grease pencil datablocks directly from main*/ 01245 for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) { 01246 /* only show if gpd is used by something... */ 01247 if (ID_REAL_USERS(gpd) < 1) 01248 continue; 01249 01250 /* add gpd as channel too (if for drawing, and it has layers) */ 01251 if ((filter_mode & ANIMFILTER_CHANNELS) && (gpd->layers.first)) { 01252 /* add to list */ 01253 ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, NULL, ANIMTYPE_NONE, NULL); 01254 if (ale) { 01255 BLI_addtail(anim_data, ale); 01256 items++; 01257 } 01258 } 01259 01260 /* only add layers if they will be visible (if drawing channels) */ 01261 if ( !(filter_mode & ANIMFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) { 01262 /* loop over layers as the conditions are acceptable */ 01263 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { 01264 /* only if selected */ 01265 if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) { 01266 /* only if editable */ 01267 if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) { 01268 /* add to list */ 01269 ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK, (ID*)gpd); 01270 if (ale) { 01271 BLI_addtail(anim_data, ale); 01272 items++; 01273 } 01274 } 01275 } 01276 } 01277 } 01278 } 01279 } 01280 01281 /* return the number of items added to the list */ 01282 return items; 01283 } 01284 01285 /* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */ 01286 static int animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode) 01287 { 01288 ListBase texs = {NULL, NULL}; 01289 LinkData *ld; 01290 MTex **mtex = NULL; 01291 short expanded=0; 01292 int ownertype = ANIMTYPE_NONE; 01293 01294 bAnimListElem *ale=NULL; 01295 int items=0, a=0; 01296 01297 /* get datatype specific data first */ 01298 if (owner_id == NULL) 01299 return 0; 01300 01301 switch (GS(owner_id->name)) { 01302 case ID_MA: 01303 { 01304 Material *ma= (Material *)owner_id; 01305 01306 mtex= (MTex**)(&ma->mtex); 01307 expanded= FILTER_TEX_MATC(ma); 01308 ownertype= ANIMTYPE_DSMAT; 01309 } 01310 break; 01311 case ID_LA: 01312 { 01313 Lamp *la= (Lamp *)owner_id; 01314 01315 mtex= (MTex**)(&la->mtex); 01316 expanded= FILTER_TEX_LAMC(la); 01317 ownertype= ANIMTYPE_DSLAM; 01318 } 01319 break; 01320 case ID_WO: 01321 { 01322 World *wo= (World *)owner_id; 01323 01324 mtex= (MTex**)(&wo->mtex); 01325 expanded= FILTER_TEX_WORC(wo); 01326 ownertype= ANIMTYPE_DSWOR; 01327 } 01328 break; 01329 default: 01330 { 01331 /* invalid/unsupported option */ 01332 if (G.f & G_DEBUG) 01333 printf("ERROR: unsupported owner_id (i.e. texture stack) for filter textures - %s \n", owner_id->name); 01334 return 0; 01335 } 01336 } 01337 01338 /* firstly check that we actuallly have some textures, by gathering all textures in a temp list */ 01339 for (a=0; a < MAX_MTEX; a++) { 01340 Tex *tex= (mtex[a]) ? mtex[a]->tex : NULL; 01341 short ok = 0; 01342 01343 /* for now, if no texture returned, skip (this shouldn't confuse the user I hope) */ 01344 if (ELEM(NULL, tex, tex->adt)) 01345 continue; 01346 01347 /* check if ok */ 01348 ANIMDATA_FILTER_CASES(tex, 01349 { /* AnimData blocks - do nothing... */ }, 01350 ok=1;, 01351 ok=1;, 01352 ok=1;) 01353 if (ok == 0) continue; 01354 01355 /* make a temp list elem for this */ 01356 ld= MEM_callocN(sizeof(LinkData), "DopeSheet-TextureCache"); 01357 ld->data= tex; 01358 BLI_addtail(&texs, ld); 01359 } 01360 01361 /* if there were no channels found, no need to carry on */ 01362 if (texs.first == NULL) 01363 return 0; 01364 01365 /* include textures-expand widget? */ 01366 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01367 ale= make_new_animlistelem(owner_id, ANIMTYPE_FILLTEXD, owner_id, ownertype, owner_id); 01368 if (ale) { 01369 BLI_addtail(anim_data, ale); 01370 items++; 01371 } 01372 } 01373 01374 /* add textures */ 01375 if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01376 /* for each texture in cache, add channels */ 01377 for (ld= texs.first; ld; ld= ld->next) { 01378 Tex *tex= (Tex *)ld->data; 01379 01380 /* include texture-expand widget? */ 01381 if (filter_mode & ANIMFILTER_CHANNELS) { 01382 /* check if filtering by active status */ 01383 if ANIMCHANNEL_ACTIVEOK(tex) { 01384 ale= make_new_animlistelem(tex, ANIMTYPE_DSTEX, owner_id, ownertype, owner_id); 01385 if (ale) { 01386 BLI_addtail(anim_data, ale); 01387 items++; 01388 } 01389 } 01390 } 01391 01392 /* add texture's animation data 01393 * NOTE: for these, we make the owner/ownertype the material/lamp/etc. not the texture, otherwise the 01394 * drawing code cannot resolve the indention easily 01395 */ 01396 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_TEX_DATA(tex) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01397 ANIMDATA_FILTER_CASES(tex, 01398 { /* AnimData blocks - do nothing... */ }, 01399 items += animdata_filter_nla(ac, anim_data, ads, tex->adt, filter_mode, owner_id, ownertype, (ID *)tex);, 01400 items += animdata_filter_fcurves(anim_data, ads, tex->adt->drivers.first, NULL, owner_id, ownertype, filter_mode, (ID *)tex);, 01401 items += animdata_filter_action(ac, anim_data, ads, tex->adt->action, filter_mode, owner_id, ownertype, (ID *)tex);) 01402 } 01403 } 01404 } 01405 01406 /* free cache */ 01407 BLI_freelistN(&texs); 01408 01409 /* return the number of items added to the list */ 01410 return items; 01411 } 01412 01413 static int animdata_filter_dopesheet_mats (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode) 01414 { 01415 ListBase mats = {NULL, NULL}; 01416 LinkData *ld; 01417 01418 bAnimListElem *ale=NULL; 01419 Object *ob= base->object; 01420 int items=0, a=0; 01421 01422 /* firstly check that we actuallly have some materials, by gathering all materials in a temp list */ 01423 for (a=1; a <= ob->totcol; a++) { 01424 Material *ma= give_current_material(ob, a); 01425 short ok = 0; 01426 01427 /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */ 01428 if (ma == NULL) continue; 01429 01430 /* check if ok */ 01431 ANIMDATA_FILTER_CASES(ma, 01432 { /* AnimData blocks - do nothing... */ }, 01433 ok=1;, 01434 ok=1;, 01435 ok=1;) 01436 01437 /* need to check textures */ 01438 if (ok == 0 && !(ads->filterflag & ADS_FILTER_NOTEX)) { 01439 int mtInd; 01440 01441 for (mtInd=0; mtInd < MAX_MTEX; mtInd++) { 01442 MTex *mtex = ma->mtex[mtInd]; 01443 01444 if(mtex && mtex->tex) { 01445 ANIMDATA_FILTER_CASES(mtex->tex, 01446 { /* AnimData blocks - do nothing... */ }, 01447 ok=1;, 01448 ok=1;, 01449 ok=1;) 01450 } 01451 01452 if(ok) 01453 break; 01454 } 01455 } 01456 01457 if (ok == 0) continue; 01458 01459 /* make a temp list elem for this */ 01460 ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache"); 01461 ld->data= ma; 01462 BLI_addtail(&mats, ld); 01463 } 01464 01465 /* if there were no channels found, no need to carry on */ 01466 if (mats.first == NULL) 01467 return 0; 01468 01469 /* include materials-expand widget? */ 01470 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01471 ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT, (ID *)ob); 01472 if (ale) { 01473 BLI_addtail(anim_data, ale); 01474 items++; 01475 } 01476 } 01477 01478 /* add materials? */ 01479 if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01480 /* for each material in cache, add channels */ 01481 for (ld= mats.first; ld; ld= ld->next) { 01482 Material *ma= (Material *)ld->data; 01483 01484 /* include material-expand widget? */ 01485 // hmm... do we need to store the index of this material in the array anywhere? 01486 if (filter_mode & ANIMFILTER_CHANNELS) { 01487 /* check if filtering by active status */ 01488 if ANIMCHANNEL_ACTIVEOK(ma) { 01489 ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma); 01490 if (ale) { 01491 BLI_addtail(anim_data, ale); 01492 items++; 01493 } 01494 } 01495 } 01496 01497 /* add material's animation data */ 01498 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01499 /* material's animation data */ 01500 ANIMDATA_FILTER_CASES(ma, 01501 { /* AnimData blocks - do nothing... */ }, 01502 items += animdata_filter_nla(ac, anim_data, ads, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, 01503 items += animdata_filter_fcurves(anim_data, ads, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);, 01504 items += animdata_filter_action(ac, anim_data, ads, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);) 01505 01506 /* textures */ 01507 if (!(ads->filterflag & ADS_FILTER_NOTEX)) 01508 items += animdata_filter_dopesheet_texs(ac, anim_data, ads, (ID *)ma, filter_mode); 01509 } 01510 } 01511 } 01512 01513 /* free cache */ 01514 BLI_freelistN(&mats); 01515 01516 /* return the number of items added to the list */ 01517 return items; 01518 } 01519 01520 static int animdata_filter_dopesheet_particles (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode) 01521 { 01522 bAnimListElem *ale=NULL; 01523 Object *ob= base->object; 01524 ParticleSystem *psys = ob->particlesystem.first; 01525 int items= 0, first = 1; 01526 01527 for(; psys; psys=psys->next) { 01528 short ok = 0; 01529 01530 if(ELEM(NULL, psys->part, psys->part->adt)) 01531 continue; 01532 01533 ANIMDATA_FILTER_CASES(psys->part, 01534 { /* AnimData blocks - do nothing... */ }, 01535 ok=1;, 01536 ok=1;, 01537 ok=1;) 01538 if (ok == 0) continue; 01539 01540 /* include particles-expand widget? */ 01541 if (first && (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01542 ale= make_new_animlistelem(ob, ANIMTYPE_FILLPARTD, base, ANIMTYPE_OBJECT, (ID *)ob); 01543 if (ale) { 01544 BLI_addtail(anim_data, ale); 01545 items++; 01546 } 01547 first = 0; 01548 } 01549 01550 /* add particle settings? */ 01551 if (FILTER_PART_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01552 if ((filter_mode & ANIMFILTER_CHANNELS)) { 01553 /* check if filtering by active status */ 01554 if ANIMCHANNEL_ACTIVEOK(psys->part) { 01555 ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part); 01556 if (ale) { 01557 BLI_addtail(anim_data, ale); 01558 items++; 01559 } 01560 } 01561 } 01562 01563 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01564 ANIMDATA_FILTER_CASES(psys->part, 01565 { /* AnimData blocks - do nothing... */ }, 01566 items += animdata_filter_nla(ac, anim_data, ads, psys->part->adt, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);, 01567 items += animdata_filter_fcurves(anim_data, ads, psys->part->adt->drivers.first, NULL, psys->part, ANIMTYPE_DSPART, filter_mode, (ID *)psys->part);, 01568 items += animdata_filter_action(ac, anim_data, ads, psys->part->adt->action, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);) 01569 } 01570 } 01571 } 01572 01573 /* return the number of items added to the list */ 01574 return items; 01575 } 01576 01577 static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode) 01578 { 01579 bAnimListElem *ale=NULL; 01580 Object *ob= base->object; 01581 IdAdtTemplate *iat= ob->data; 01582 AnimData *adt= iat->adt; 01583 short type=0, expanded=0; 01584 int items= 0; 01585 01586 /* get settings based on data type */ 01587 switch (ob->type) { 01588 case OB_CAMERA: /* ------- Camera ------------ */ 01589 { 01590 Camera *ca= (Camera *)ob->data; 01591 01592 type= ANIMTYPE_DSCAM; 01593 expanded= FILTER_CAM_OBJD(ca); 01594 } 01595 break; 01596 case OB_LAMP: /* ---------- Lamp ----------- */ 01597 { 01598 Lamp *la= (Lamp *)ob->data; 01599 01600 type= ANIMTYPE_DSLAM; 01601 expanded= FILTER_LAM_OBJD(la); 01602 } 01603 break; 01604 case OB_CURVE: /* ------- Curve ---------- */ 01605 case OB_SURF: /* ------- Nurbs Surface ---------- */ 01606 case OB_FONT: /* ------- Text Curve ---------- */ 01607 { 01608 Curve *cu= (Curve *)ob->data; 01609 01610 type= ANIMTYPE_DSCUR; 01611 expanded= FILTER_CUR_OBJD(cu); 01612 } 01613 break; 01614 case OB_MBALL: /* ------- MetaBall ---------- */ 01615 { 01616 MetaBall *mb= (MetaBall *)ob->data; 01617 01618 type= ANIMTYPE_DSMBALL; 01619 expanded= FILTER_MBALL_OBJD(mb); 01620 } 01621 break; 01622 case OB_ARMATURE: /* ------- Armature ---------- */ 01623 { 01624 bArmature *arm= (bArmature *)ob->data; 01625 01626 type= ANIMTYPE_DSARM; 01627 expanded= FILTER_ARM_OBJD(arm); 01628 } 01629 break; 01630 case OB_MESH: /* ------- Mesh ---------- */ 01631 { 01632 Mesh *me= (Mesh *)ob->data; 01633 01634 type= ANIMTYPE_DSMESH; 01635 expanded= FILTER_MESH_OBJD(me); 01636 } 01637 break; 01638 case OB_LATTICE: /* ---- Lattice ---- */ 01639 { 01640 Lattice *lt = (Lattice *)ob->data; 01641 01642 type= ANIMTYPE_DSLAT; 01643 expanded= FILTER_LATTICE_OBJD(lt); 01644 } 01645 break; 01646 } 01647 01648 /* include data-expand widget? */ 01649 if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { 01650 /* check if filtering by active status */ 01651 if ANIMCHANNEL_ACTIVEOK(iat) { 01652 ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat); 01653 if (ale) BLI_addtail(anim_data, ale); 01654 } 01655 } 01656 01657 /* add object-data animation channels? */ 01658 if (!(filter_mode & ANIMFILTER_VISIBLE) || (expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01659 /* filtering for channels - nla, drivers, keyframes */ 01660 ANIMDATA_FILTER_CASES(iat, 01661 { /* AnimData blocks - do nothing... */ }, 01662 items+= animdata_filter_nla(ac, anim_data, ads, iat->adt, filter_mode, iat, type, (ID *)iat);, 01663 items+= animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);, 01664 items+= animdata_filter_action(ac, anim_data, ads, iat->adt->action, filter_mode, iat, type, (ID *)iat);) 01665 01666 /* sub-data filtering... */ 01667 switch (ob->type) { 01668 case OB_LAMP: /* lamp - textures */ 01669 { 01670 /* textures */ 01671 if (!(ads->filterflag & ADS_FILTER_NOTEX)) 01672 items += animdata_filter_dopesheet_texs(ac, anim_data, ads, ob->data, filter_mode); 01673 } 01674 break; 01675 } 01676 } 01677 01678 /* return the number of items added to the list */ 01679 return items; 01680 } 01681 01682 static int animdata_filter_dopesheet_ob (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode) 01683 { 01684 bAnimListElem *ale=NULL; 01685 AnimData *adt = NULL; 01686 Object *ob= base->object; 01687 Key *key= ob_get_key(ob); 01688 short obdata_ok = 0; 01689 int items = 0; 01690 01691 /* add this object as a channel first */ 01692 if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) { 01693 /* check if filtering by selection */ 01694 if ANIMCHANNEL_SELOK((base->flag & SELECT)) { 01695 /* check if filtering by active status */ 01696 if ANIMCHANNEL_ACTIVEOK(ob) { 01697 ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, (ID *)ob); 01698 if (ale) { 01699 BLI_addtail(anim_data, ale); 01700 items++; 01701 } 01702 } 01703 } 01704 } 01705 01706 /* if collapsed, don't go any further (unless adding keyframes only) */ 01707 if ( ((filter_mode & ANIMFILTER_VISIBLE) && EXPANDED_OBJC(ob) == 0) && 01708 !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) ) 01709 return items; 01710 01711 /* Action, Drivers, or NLA */ 01712 if (ob->adt && !(ads->filterflag & ADS_FILTER_NOOBJ)) { 01713 adt= ob->adt; 01714 ANIMDATA_FILTER_CASES(ob, 01715 { /* AnimData blocks - do nothing... */ }, 01716 { /* nla */ 01717 /* add NLA tracks */ 01718 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); 01719 }, 01720 { /* drivers */ 01721 /* include drivers-expand widget? */ 01722 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01723 ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob); 01724 if (ale) { 01725 BLI_addtail(anim_data, ale); 01726 items++; 01727 } 01728 } 01729 01730 /* add F-Curve channels (drivers are F-Curves) */ 01731 if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) { 01732 // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?) 01733 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob); 01734 } 01735 }, 01736 { /* action (keyframes) */ 01737 /* include action-expand widget? */ 01738 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01739 ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob); 01740 if (ale) { 01741 BLI_addtail(anim_data, ale); 01742 items++; 01743 } 01744 } 01745 01746 /* add F-Curve channels? */ 01747 if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) { 01748 // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?) 01749 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); 01750 } 01751 } 01752 ); 01753 } 01754 01755 01756 /* ShapeKeys? */ 01757 if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) { 01758 adt= key->adt; 01759 ANIMDATA_FILTER_CASES(key, 01760 { /* AnimData blocks - do nothing... */ }, 01761 { /* nla */ 01762 /* include shapekey-expand widget? */ 01763 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01764 /* check if filtering by active status */ 01765 if ANIMCHANNEL_ACTIVEOK(key) { 01766 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob); 01767 if (ale) { 01768 BLI_addtail(anim_data, ale); 01769 items++; 01770 } 01771 } 01772 } 01773 01774 /* add NLA tracks - only if expanded or so */ 01775 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) 01776 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)key); 01777 }, 01778 { /* drivers */ 01779 /* include shapekey-expand widget? */ 01780 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01781 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob); 01782 if (ale) { 01783 BLI_addtail(anim_data, ale); 01784 items++; 01785 } 01786 } 01787 01788 /* add channels */ 01789 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01790 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, key, ANIMTYPE_DSSKEY, filter_mode, (ID *)key); 01791 } 01792 }, 01793 { /* action (keyframes) */ 01794 /* include shapekey-expand widget? */ 01795 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01796 /* check if filtering by active status */ 01797 if ANIMCHANNEL_ACTIVEOK(key) { 01798 ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob); 01799 if (ale) { 01800 BLI_addtail(anim_data, ale); 01801 items++; 01802 } 01803 } 01804 } 01805 01806 /* add channels */ 01807 if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) { 01808 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, key, ANIMTYPE_DSSKEY, (ID *)key); 01809 } 01810 } 01811 ); 01812 } 01813 01814 /* Materials? */ 01815 if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) 01816 items += animdata_filter_dopesheet_mats(ac, anim_data, ads, base, filter_mode); 01817 01818 /* Object Data */ 01819 switch (ob->type) { 01820 case OB_CAMERA: /* ------- Camera ------------ */ 01821 { 01822 Camera *ca= (Camera *)ob->data; 01823 01824 if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) { 01825 ANIMDATA_FILTER_CASES(ca, 01826 { /* AnimData blocks - do nothing... */ }, 01827 obdata_ok= 1;, 01828 obdata_ok= 1;, 01829 obdata_ok= 1;) 01830 } 01831 } 01832 break; 01833 case OB_LAMP: /* ---------- Lamp ----------- */ 01834 { 01835 Lamp *la= (Lamp *)ob->data; 01836 01837 if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) { 01838 ANIMDATA_FILTER_CASES(la, 01839 { /* AnimData blocks - do nothing... */ }, 01840 obdata_ok= 1;, 01841 obdata_ok= 1;, 01842 obdata_ok= 1;) 01843 } 01844 } 01845 break; 01846 case OB_CURVE: /* ------- Curve ---------- */ 01847 case OB_SURF: /* ------- Nurbs Surface ---------- */ 01848 case OB_FONT: /* ------- Text Curve ---------- */ 01849 { 01850 Curve *cu= (Curve *)ob->data; 01851 01852 if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) { 01853 ANIMDATA_FILTER_CASES(cu, 01854 { /* AnimData blocks - do nothing... */ }, 01855 obdata_ok= 1;, 01856 obdata_ok= 1;, 01857 obdata_ok= 1;) 01858 } 01859 } 01860 break; 01861 case OB_MBALL: /* ------- MetaBall ---------- */ 01862 { 01863 MetaBall *mb= (MetaBall *)ob->data; 01864 01865 if ((ads->filterflag & ADS_FILTER_NOMBA) == 0) { 01866 ANIMDATA_FILTER_CASES(mb, 01867 { /* AnimData blocks - do nothing... */ }, 01868 obdata_ok= 1;, 01869 obdata_ok= 1;, 01870 obdata_ok= 1;) 01871 } 01872 } 01873 break; 01874 case OB_ARMATURE: /* ------- Armature ---------- */ 01875 { 01876 bArmature *arm= (bArmature *)ob->data; 01877 01878 if ((ads->filterflag & ADS_FILTER_NOARM) == 0) { 01879 ANIMDATA_FILTER_CASES(arm, 01880 { /* AnimData blocks - do nothing... */ }, 01881 obdata_ok= 1;, 01882 obdata_ok= 1;, 01883 obdata_ok= 1;) 01884 } 01885 } 01886 break; 01887 case OB_MESH: /* ------- Mesh ---------- */ 01888 { 01889 Mesh *me= (Mesh *)ob->data; 01890 01891 if ((ads->filterflag & ADS_FILTER_NOMESH) == 0) { 01892 ANIMDATA_FILTER_CASES(me, 01893 { /* AnimData blocks - do nothing... */ }, 01894 obdata_ok= 1;, 01895 obdata_ok= 1;, 01896 obdata_ok= 1;) 01897 } 01898 } 01899 break; 01900 case OB_LATTICE: /* ------- Lattice ---------- */ 01901 { 01902 Lattice *lt= (Lattice *)ob->data; 01903 01904 if ((ads->filterflag & ADS_FILTER_NOLAT) == 0) { 01905 ANIMDATA_FILTER_CASES(lt, 01906 { /* AnimData blocks - do nothing... */ }, 01907 obdata_ok= 1;, 01908 obdata_ok= 1;, 01909 obdata_ok= 1;) 01910 } 01911 } 01912 break; 01913 } 01914 if (obdata_ok) 01915 items += animdata_filter_dopesheet_obdata(ac, anim_data, ads, base, filter_mode); 01916 01917 /* particles */ 01918 if (ob->particlesystem.first && !(ads->filterflag & ADS_FILTER_NOPART)) 01919 items += animdata_filter_dopesheet_particles(ac, anim_data, ads, base, filter_mode); 01920 01921 /* return the number of items added to the list */ 01922 return items; 01923 } 01924 01925 static int animdata_filter_dopesheet_scene (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode) 01926 { 01927 World *wo= sce->world; 01928 bNodeTree *ntree= sce->nodetree; 01929 AnimData *adt= NULL; 01930 bAnimListElem *ale; 01931 int items = 0; 01932 01933 /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */ 01934 if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) { 01935 /* check if filtering by selection */ 01936 if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) { 01937 ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL); 01938 if (ale) { 01939 BLI_addtail(anim_data, ale); 01940 items++; 01941 } 01942 } 01943 } 01944 01945 /* if collapsed, don't go any further (unless adding keyframes only) */ 01946 if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) ) 01947 return items; 01948 01949 /* Action, Drivers, or NLA for Scene */ 01950 if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) { 01951 adt= sce->adt; 01952 ANIMDATA_FILTER_CASES(sce, 01953 { /* AnimData blocks - do nothing... */ }, 01954 { /* nla */ 01955 /* add NLA tracks */ 01956 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); 01957 }, 01958 { /* drivers */ 01959 /* include drivers-expand widget? */ 01960 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01961 ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce); 01962 if (ale) { 01963 BLI_addtail(anim_data, ale); 01964 items++; 01965 } 01966 } 01967 01968 /* add F-Curve channels (drivers are F-Curves) */ 01969 if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) { 01970 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce); 01971 } 01972 }, 01973 { /* action */ 01974 /* include action-expand widget? */ 01975 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 01976 ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce); 01977 if (ale) { 01978 BLI_addtail(anim_data, ale); 01979 items++; 01980 } 01981 } 01982 01983 /* add F-Curve channels? */ 01984 if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) { 01985 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce); 01986 } 01987 } 01988 ) 01989 } 01990 01991 /* world */ 01992 if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) { 01993 /* Action, Drivers, or NLA for World */ 01994 adt= wo->adt; 01995 ANIMDATA_FILTER_CASES(wo, 01996 { /* AnimData blocks - do nothing... */ }, 01997 { /* nla */ 01998 /* add NLA tracks */ 01999 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); 02000 }, 02001 { /* drivers */ 02002 /* include world-expand widget? */ 02003 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 02004 ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo); 02005 if (ale) { 02006 BLI_addtail(anim_data, ale); 02007 items++; 02008 } 02009 } 02010 02011 /* add F-Curve channels (drivers are F-Curves) */ 02012 if (FILTER_WOR_SCED(wo)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) { 02013 // XXX owner info is messed up now... 02014 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo); 02015 } 02016 }, 02017 { /* action */ 02018 /* include world-expand widget? */ 02019 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 02020 ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce); 02021 if (ale) { 02022 BLI_addtail(anim_data, ale); 02023 items++; 02024 } 02025 } 02026 02027 /* add channels */ 02028 if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) { 02029 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo); 02030 } 02031 } 02032 ) 02033 02034 /* if expanded, check world textures too */ 02035 if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) { 02036 /* textures for world */ 02037 if (!(ads->filterflag & ADS_FILTER_NOTEX)) 02038 items += animdata_filter_dopesheet_texs(ac, anim_data, ads, (ID *)wo, filter_mode); 02039 } 02040 } 02041 /* nodetree */ 02042 if ((ntree && ntree->adt) && !(ads->filterflag & ADS_FILTER_NONTREE)) { 02043 /* Action, Drivers, or NLA for Nodetree */ 02044 adt= ntree->adt; 02045 ANIMDATA_FILTER_CASES(ntree, 02046 { /* AnimData blocks - do nothing... */ }, 02047 { /* nla */ 02048 /* add NLA tracks */ 02049 items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree); 02050 }, 02051 { /* drivers */ 02052 /* include nodetree-expand widget? */ 02053 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 02054 ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)ntree); 02055 if (ale) { 02056 BLI_addtail(anim_data, ale); 02057 items++; 02058 } 02059 } 02060 02061 /* add F-Curve channels (drivers are F-Curves) */ 02062 if (FILTER_NTREE_SCED(ntree)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) { 02063 // XXX owner info is messed up now... 02064 items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ntree, ANIMTYPE_DSNTREE, filter_mode, (ID *)ntree); 02065 } 02066 }, 02067 { /* action */ 02068 /* include nodetree-expand widget? */ 02069 if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { 02070 ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)sce); 02071 if (ale) { 02072 BLI_addtail(anim_data, ale); 02073 items++; 02074 } 02075 } 02076 02077 /* add channels */ 02078 if (FILTER_NTREE_SCED(ntree) || (filter_mode & ANIMFILTER_CURVESONLY)) { 02079 items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree); 02080 } 02081 } 02082 ) 02083 } 02084 02085 02086 // TODO: scene compositing nodes (these aren't standard node-trees) 02087 02088 /* return the number of items added to the list */ 02089 return items; 02090 } 02091 02092 // TODO: implement pinning... (if and when pinning is done, what we need to do is to provide freeing mechanisms - to protect against data that was deleted) 02093 static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode) 02094 { 02095 Scene *sce= (Scene *)ads->source; 02096 Base *base; 02097 bAnimListElem *ale; 02098 int items = 0; 02099 02100 /* check that we do indeed have a scene */ 02101 if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) { 02102 printf("DopeSheet Error: Not scene!\n"); 02103 if (G.f & G_DEBUG) 02104 printf("\tPointer = %p, Name = '%s' \n", (void *)ads->source, (ads->source)?ads->source->name:NULL); 02105 return 0; 02106 } 02107 02108 /* augment the filter-flags with settings based on the dopesheet filterflags 02109 * so that some temp settings can get added automagically... 02110 */ 02111 if (ads->filterflag & ADS_FILTER_SELEDIT) { 02112 /* only selected F-Curves should get their keyframes considered for editability */ 02113 filter_mode |= ANIMFILTER_SELEDIT; 02114 } 02115 02116 /* scene-linked animation */ 02117 // TODO: sequencer, composite nodes - are we to include those here too? 02118 { 02119 short sceOk= 0, worOk= 0, nodeOk=0; 02120 02121 /* check filtering-flags if ok */ 02122 ANIMDATA_FILTER_CASES(sce, 02123 { 02124 /* for the special AnimData blocks only case, we only need to add 02125 * the block if it is valid... then other cases just get skipped (hence ok=0) 02126 */ 02127 ANIMDATA_ADD_ANIMDATA(sce); 02128 sceOk=0; 02129 }, 02130 sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, 02131 sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);, 02132 sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);) 02133 if (sce->world) { 02134 ANIMDATA_FILTER_CASES(sce->world, 02135 { 02136 /* for the special AnimData blocks only case, we only need to add 02137 * the block if it is valid... then other cases just get skipped (hence ok=0) 02138 */ 02139 ANIMDATA_ADD_ANIMDATA(sce->world); 02140 worOk=0; 02141 }, 02142 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, 02143 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);, 02144 worOk= !(ads->filterflag & ADS_FILTER_NOWOR);) 02145 } 02146 if (sce->nodetree) { 02147 ANIMDATA_FILTER_CASES(sce->nodetree, 02148 { 02149 /* for the special AnimData blocks only case, we only need to add 02150 * the block if it is valid... then other cases just get skipped (hence ok=0) 02151 */ 02152 ANIMDATA_ADD_ANIMDATA(sce->nodetree); 02153 nodeOk=0; 02154 }, 02155 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);, 02156 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);, 02157 nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);) 02158 } 02159 02160 /* if only F-Curves with visible flags set can be shown, check that 02161 * datablocks haven't been set to invisible 02162 */ 02163 if (filter_mode & ANIMFILTER_CURVEVISIBLE) { 02164 if ((sce->adt) && (sce->adt->flag & ADT_CURVES_NOT_VISIBLE)) 02165 sceOk= worOk= nodeOk= 0; 02166 } 02167 02168 /* check if not all bad (i.e. so there is something to show) */ 02169 if ( !(!sceOk && !worOk && !nodeOk) ) { 02170 /* add scene data to the list of filtered channels */ 02171 items += animdata_filter_dopesheet_scene(ac, anim_data, ads, sce, filter_mode); 02172 } 02173 } 02174 02175 02176 /* loop over all bases in the scene */ 02177 for (base= sce->base.first; base; base= base->next) { 02178 /* check if there's an object (all the relevant checks are done in the ob-function) */ 02179 if (base->object) { 02180 Object *ob= base->object; 02181 Key *key= ob_get_key(ob); 02182 short actOk=1, keyOk=1, dataOk=1, matOk=1, partOk=1; 02183 02184 /* firstly, check if object can be included, by the following factors: 02185 * - if only visible, must check for layer and also viewport visibility 02186 * --> while tools may demand only visible, user setting takes priority 02187 * as user option controls whether sets of channels get included while 02188 * tool-flag takes into account collapsed/open channels too 02189 * - if only selected, must check if object is selected 02190 * - there must be animation data to edit 02191 */ 02192 // TODO: if cache is implemented, just check name here, and then 02193 if ((filter_mode & ANIMFILTER_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) { 02194 /* layer visibility - we check both object and base, since these may not be in sync yet */ 02195 if ((sce->lay & (ob->lay|base->lay))==0) continue; 02196 02197 /* outliner restrict-flag */ 02198 if (ob->restrictflag & OB_RESTRICT_VIEW) continue; 02199 } 02200 02201 /* if only F-Curves with visible flags set can be shown, check that 02202 * datablock hasn't been set to invisible 02203 */ 02204 if (filter_mode & ANIMFILTER_CURVEVISIBLE) { 02205 if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE)) 02206 continue; 02207 } 02208 02209 /* additionally, dopesheet filtering also affects what objects to consider */ 02210 { 02211 /* check selection and object type filters */ 02212 if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) ) { 02213 /* only selected should be shown */ 02214 continue; 02215 } 02216 02217 /* check if object belongs to the filtering group if option to filter 02218 * objects by the grouped status is on 02219 * - used to ease the process of doing multiple-character choreographies 02220 */ 02221 if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) { 02222 if (object_in_group(ob, ads->filter_grp) == 0) 02223 continue; 02224 } 02225 02226 /* check filters for datatypes */ 02227 /* object */ 02228 actOk= 0; 02229 if (!(ads->filterflag & ADS_FILTER_NOOBJ)) { 02230 ANIMDATA_FILTER_CASES(ob, 02231 { 02232 /* for the special AnimData blocks only case, we only need to add 02233 * the block if it is valid... then other cases just get skipped (hence ok=0) 02234 */ 02235 ANIMDATA_ADD_ANIMDATA(ob); 02236 actOk=0; 02237 }, 02238 actOk= 1;, 02239 actOk= 1;, 02240 actOk= 1;) 02241 } 02242 02243 keyOk= 0; 02244 if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) { 02245 /* shapekeys */ 02246 ANIMDATA_FILTER_CASES(key, 02247 { 02248 /* for the special AnimData blocks only case, we only need to add 02249 * the block if it is valid... then other cases just get skipped (hence ok=0) 02250 */ 02251 ANIMDATA_ADD_ANIMDATA(key); 02252 keyOk=0; 02253 }, 02254 keyOk= 1;, 02255 keyOk= 1;, 02256 keyOk= 1;) 02257 } 02258 02259 /* materials - only for geometric types */ 02260 matOk= 0; /* by default, not ok... */ 02261 if ( !(ads->filterflag & ADS_FILTER_NOMAT) && (ob->totcol) && 02262 ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) ) 02263 { 02264 int a; 02265 02266 /* firstly check that we actuallly have some materials */ 02267 for (a=1; a <= ob->totcol; a++) { 02268 Material *ma= give_current_material(ob, a); 02269 02270 if (ma) { 02271 /* if material has relevant animation data, break */ 02272 ANIMDATA_FILTER_CASES(ma, 02273 { 02274 /* for the special AnimData blocks only case, we only need to add 02275 * the block if it is valid... then other cases just get skipped (hence ok=0) 02276 */ 02277 ANIMDATA_ADD_ANIMDATA(ma); 02278 matOk=0; 02279 }, 02280 matOk= 1;, 02281 matOk= 1;, 02282 matOk= 1;) 02283 02284 if (matOk) 02285 break; 02286 02287 /* textures? */ 02288 // TODO: make this a macro that is used in the other checks too 02289 // NOTE: this has little use on its own, since the actual filtering still ignores if no anim on the data 02290 if (!(ads->filterflag & ADS_FILTER_NOTEX)) { 02291 int mtInd; 02292 02293 for (mtInd= 0; mtInd < MAX_MTEX; mtInd++) { 02294 MTex *mtex= ma->mtex[mtInd]; 02295 02296 if (mtex && mtex->tex) { 02297 /* if texture has relevant animation data, break */ 02298 ANIMDATA_FILTER_CASES(mtex->tex, 02299 { 02300 /* for the special AnimData blocks only case, we only need to add 02301 * the block if it is valid... then other cases just get skipped (hence ok=0) 02302 */ 02303 ANIMDATA_ADD_ANIMDATA(mtex->tex); 02304 matOk=0; 02305 }, 02306 matOk= 1;, 02307 matOk= 1;, 02308 matOk= 1;) 02309 02310 if (matOk) 02311 break; 02312 } 02313 } 02314 } 02315 02316 } 02317 } 02318 } 02319 02320 /* data */ 02321 switch (ob->type) { 02322 case OB_CAMERA: /* ------- Camera ------------ */ 02323 { 02324 Camera *ca= (Camera *)ob->data; 02325 dataOk= 0; 02326 ANIMDATA_FILTER_CASES(ca, 02327 if ((ads->filterflag & ADS_FILTER_NOCAM)==0) { 02328 /* for the special AnimData blocks only case, we only need to add 02329 * the block if it is valid... then other cases just get skipped (hence ok=0) 02330 */ 02331 ANIMDATA_ADD_ANIMDATA(ca); 02332 dataOk=0; 02333 }, 02334 dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, 02335 dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);, 02336 dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);) 02337 } 02338 break; 02339 case OB_LAMP: /* ---------- Lamp ----------- */ 02340 { 02341 Lamp *la= (Lamp *)ob->data; 02342 dataOk= 0; 02343 ANIMDATA_FILTER_CASES(la, 02344 if ((ads->filterflag & ADS_FILTER_NOLAM)==0) { 02345 /* for the special AnimData blocks only case, we only need to add 02346 * the block if it is valid... then other cases just get skipped (hence ok=0) 02347 */ 02348 ANIMDATA_ADD_ANIMDATA(la); 02349 dataOk=0; 02350 }, 02351 dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, 02352 dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);, 02353 dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);) 02354 } 02355 break; 02356 case OB_CURVE: /* ------- Curve ---------- */ 02357 case OB_SURF: /* ------- Nurbs Surface ---------- */ 02358 case OB_FONT: /* ------- Text Curve ---------- */ 02359 { 02360 Curve *cu= (Curve *)ob->data; 02361 dataOk= 0; 02362 ANIMDATA_FILTER_CASES(cu, 02363 if ((ads->filterflag & ADS_FILTER_NOCUR)==0) { 02364 /* for the special AnimData blocks only case, we only need to add 02365 * the block if it is valid... then other cases just get skipped (hence ok=0) 02366 */ 02367 ANIMDATA_ADD_ANIMDATA(cu); 02368 dataOk=0; 02369 }, 02370 dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, 02371 dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);, 02372 dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);) 02373 } 02374 break; 02375 case OB_MBALL: /* ------- MetaBall ---------- */ 02376 { 02377 MetaBall *mb= (MetaBall *)ob->data; 02378 dataOk= 0; 02379 ANIMDATA_FILTER_CASES(mb, 02380 if ((ads->filterflag & ADS_FILTER_NOMBA)==0) { 02381 /* for the special AnimData blocks only case, we only need to add 02382 * the block if it is valid... then other cases just get skipped (hence ok=0) 02383 */ 02384 ANIMDATA_ADD_ANIMDATA(mb); 02385 dataOk=0; 02386 }, 02387 dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);, 02388 dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);, 02389 dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);) 02390 } 02391 break; 02392 case OB_ARMATURE: /* ------- Armature ---------- */ 02393 { 02394 bArmature *arm= (bArmature *)ob->data; 02395 dataOk= 0; 02396 ANIMDATA_FILTER_CASES(arm, 02397 if ((ads->filterflag & ADS_FILTER_NOARM)==0) { 02398 /* for the special AnimData blocks only case, we only need to add 02399 * the block if it is valid... then other cases just get skipped (hence ok=0) 02400 */ 02401 ANIMDATA_ADD_ANIMDATA(arm); 02402 dataOk=0; 02403 }, 02404 dataOk= !(ads->filterflag & ADS_FILTER_NOARM);, 02405 dataOk= !(ads->filterflag & ADS_FILTER_NOARM);, 02406 dataOk= !(ads->filterflag & ADS_FILTER_NOARM);) 02407 } 02408 break; 02409 case OB_MESH: /* ------- Mesh ---------- */ 02410 { 02411 Mesh *me= (Mesh *)ob->data; 02412 dataOk= 0; 02413 ANIMDATA_FILTER_CASES(me, 02414 if ((ads->filterflag & ADS_FILTER_NOMESH)==0) { 02415 /* for the special AnimData blocks only case, we only need to add 02416 * the block if it is valid... then other cases just get skipped (hence ok=0) 02417 */ 02418 ANIMDATA_ADD_ANIMDATA(me); 02419 dataOk=0; 02420 }, 02421 dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);, 02422 dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);, 02423 dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);) 02424 } 02425 break; 02426 case OB_LATTICE: /* ------- Lattice ---------- */ 02427 { 02428 Lattice *lt= (Lattice *)ob->data; 02429 dataOk= 0; 02430 ANIMDATA_FILTER_CASES(lt, 02431 if ((ads->filterflag & ADS_FILTER_NOLAT)==0) { 02432 /* for the special AnimData blocks only case, we only need to add 02433 * the block if it is valid... then other cases just get skipped (hence ok=0) 02434 */ 02435 ANIMDATA_ADD_ANIMDATA(lt); 02436 dataOk=0; 02437 }, 02438 dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);, 02439 dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);, 02440 dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);) 02441 } 02442 break; 02443 default: /* --- other --- */ 02444 dataOk= 0; 02445 break; 02446 } 02447 02448 /* particles */ 02449 partOk = 0; 02450 if (!(ads->filterflag & ADS_FILTER_NOPART) && ob->particlesystem.first) { 02451 ParticleSystem *psys = ob->particlesystem.first; 02452 for(; psys; psys=psys->next) { 02453 if (psys->part) { 02454 /* if particlesettings has relevant animation data, break */ 02455 ANIMDATA_FILTER_CASES(psys->part, 02456 { 02457 /* for the special AnimData blocks only case, we only need to add 02458 * the block if it is valid... then other cases just get skipped (hence ok=0) 02459 */ 02460 ANIMDATA_ADD_ANIMDATA(psys->part); 02461 partOk=0; 02462 }, 02463 partOk= 1;, 02464 partOk= 1;, 02465 partOk= 1;) 02466 } 02467 02468 if (partOk) 02469 break; 02470 } 02471 } 02472 02473 /* check if all bad (i.e. nothing to show) */ 02474 if (!actOk && !keyOk && !dataOk && !matOk && !partOk) 02475 continue; 02476 } 02477 02478 /* since we're still here, this object should be usable */ 02479 items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode); 02480 } 02481 } 02482 02483 /* return the number of items in the list */ 02484 return items; 02485 } 02486 02487 /* Summary track for DopeSheet/Action Editor 02488 * - return code is whether the summary lets the other channels get drawn 02489 */ 02490 static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim_data, int filter_mode, int *items) 02491 { 02492 bDopeSheet *ads = NULL; 02493 02494 /* get the DopeSheet information to use 02495 * - we should only need to deal with the DopeSheet/Action Editor, 02496 * since all the other Animation Editors won't have this concept 02497 * being applicable. 02498 */ 02499 if ((ac && ac->sa) && (ac->sa->spacetype == SPACE_ACTION)) { 02500 SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first; 02501 ads= &saction->ads; 02502 } 02503 else { 02504 /* invalid space type - skip this summary channels */ 02505 return 1; 02506 } 02507 02508 /* dopesheet summary 02509 * - only for drawing and/or selecting keyframes in channels, but not for real editing 02510 * - only useful for DopeSheet/Action/etc. editors where it is actually useful 02511 */ 02512 // TODO: we should really check if some other prohibited filters are also active, but that can be for later 02513 if ((filter_mode & ANIMFILTER_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) { 02514 bAnimListElem *ale= make_new_animlistelem(ac, ANIMTYPE_SUMMARY, NULL, ANIMTYPE_NONE, NULL); 02515 if (ale) { 02516 BLI_addtail(anim_data, ale); 02517 (*items)++; 02518 } 02519 02520 /* if summary is collapsed, don't show other channels beneath this 02521 * - this check is put inside the summary check so that it doesn't interfere with normal operation 02522 */ 02523 if (ads->flag & ADS_FLAG_SUMMARY_COLLAPSED) 02524 return 0; 02525 } 02526 02527 /* the other channels beneath this can be shown */ 02528 return 1; 02529 } 02530 02531 /* ----------- Cleanup API --------------- */ 02532 02533 /* Remove entries with invalid types in animation channel list */ 02534 static int animdata_filter_remove_invalid (ListBase *anim_data) 02535 { 02536 bAnimListElem *ale, *next; 02537 int items = 0; 02538 02539 /* only keep entries with valid types */ 02540 for (ale= anim_data->first; ale; ale= next) { 02541 next= ale->next; 02542 02543 if (ale->type == ANIMTYPE_NONE) 02544 BLI_freelinkN(anim_data, ale); 02545 else 02546 items++; 02547 } 02548 02549 return items; 02550 } 02551 02552 /* Remove duplicate entries in animation channel list */ 02553 static int animdata_filter_remove_duplis (ListBase *anim_data) 02554 { 02555 bAnimListElem *ale, *next; 02556 GHash *gh; 02557 int items = 0; 02558 02559 /* build new hashtable to efficiently store and retrieve which entries have been 02560 * encountered already while searching 02561 */ 02562 gh= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "animdata_filter_duplis_remove gh"); 02563 02564 /* loop through items, removing them from the list if a similar item occurs already */ 02565 for (ale = anim_data->first; ale; ale = next) { 02566 next = ale->next; 02567 02568 /* check if hash has any record of an entry like this 02569 * - just use ale->data for now, though it would be nicer to involve 02570 * ale->type in combination too to capture corner cases (where same data performs differently) 02571 */ 02572 if (BLI_ghash_haskey(gh, ale->data) == 0) { 02573 /* this entry is 'unique' and can be kept */ 02574 BLI_ghash_insert(gh, ale->data, NULL); 02575 items++; 02576 } 02577 else { 02578 /* this entry isn't needed anymore */ 02579 BLI_freelinkN(anim_data, ale); 02580 } 02581 } 02582 02583 /* free the hash... */ 02584 BLI_ghash_free(gh, NULL, NULL); 02585 02586 /* return the number of items still in the list */ 02587 return items; 02588 } 02589 02590 /* ----------- Public API --------------- */ 02591 02592 /* This function filters the active data source to leave only animation channels suitable for 02593 * usage by the caller. It will return the length of the list 02594 * 02595 * *anim_data: is a pointer to a ListBase, to which the filtered animation channels 02596 * will be placed for use. 02597 * filter_mode: how should the data be filtered - bitmapping accessed flags 02598 */ 02599 int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode, void *data, short datatype) 02600 { 02601 int items = 0; 02602 02603 /* only filter data if there's somewhere to put it */ 02604 if (data && anim_data) { 02605 Object *obact= (ac) ? ac->obact : NULL; 02606 02607 /* firstly filter the data */ 02608 switch (datatype) { 02609 case ANIMCONT_ACTION: /* 'Action Editor' */ 02610 { 02611 SpaceAction *saction = (SpaceAction *)ac->sa->spacedata.first; 02612 bDopeSheet *ads = (saction)? &saction->ads : NULL; 02613 02614 /* the check for the DopeSheet summary is included here since the summary works here too */ 02615 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) 02616 items += animdata_filter_action(ac, anim_data, ads, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact); 02617 } 02618 break; 02619 02620 case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */ 02621 { 02622 /* the check for the DopeSheet summary is included here since the summary works here too */ 02623 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) 02624 items= animdata_filter_shapekey(ac, anim_data, data, filter_mode); 02625 } 02626 break; 02627 02628 case ANIMCONT_GPENCIL: 02629 { 02630 items= animdata_filter_gpencil(anim_data, data, filter_mode); 02631 } 02632 break; 02633 02634 case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */ 02635 { 02636 /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */ 02637 if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) 02638 items += animdata_filter_dopesheet(ac, anim_data, data, filter_mode); 02639 } 02640 break; 02641 02642 case ANIMCONT_FCURVES: /* Graph Editor -> FCurves/Animation Editing */ 02643 case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */ 02644 case ANIMCONT_NLA: /* NLA Editor */ 02645 { 02646 /* all of these editors use the basic DopeSheet data for filtering options, but don't have all the same features */ 02647 items = animdata_filter_dopesheet(ac, anim_data, data, filter_mode); 02648 } 02649 break; 02650 } 02651 02652 /* remove any 'weedy' entries */ 02653 items = animdata_filter_remove_invalid(anim_data); 02654 02655 /* remove duplicates (if required) */ 02656 if (filter_mode & ANIMFILTER_NODUPLIS) 02657 items = animdata_filter_remove_duplis(anim_data); 02658 } 02659 02660 /* return the number of items in the list */ 02661 return items; 02662 } 02663 02664 /* ************************************************************ */