|
Blender
V2.59
|
00001 /* 00002 * $Id: keyingsets.c 36924 2011-05-26 13:38:16Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): Joshua Leung (full recode) 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include <stdio.h> 00036 #include <stddef.h> 00037 #include <string.h> 00038 #include <math.h> 00039 #include <float.h> 00040 00041 #include "MEM_guardedalloc.h" 00042 00043 #include "BLI_blenlib.h" 00044 #include "BLI_math.h" 00045 #include "BLI_dynstr.h" 00046 #include "BLI_utildefines.h" 00047 00048 #include "DNA_anim_types.h" 00049 #include "DNA_scene_types.h" 00050 #include "DNA_object_types.h" 00051 00052 #include "BKE_main.h" 00053 #include "BKE_animsys.h" 00054 #include "BKE_context.h" 00055 #include "BKE_depsgraph.h" 00056 #include "BKE_report.h" 00057 00058 #include "ED_keyframing.h" 00059 #include "ED_screen.h" 00060 00061 #include "UI_interface.h" 00062 #include "UI_resources.h" 00063 00064 #include "WM_api.h" 00065 #include "WM_types.h" 00066 00067 #include "RNA_access.h" 00068 #include "RNA_define.h" 00069 #include "RNA_enum_types.h" 00070 00071 #include "anim_intern.h" 00072 00073 /* ************************************************** */ 00074 /* KEYING SETS - OPERATORS (for use in UI panels) */ 00075 /* These operators are really duplication of existing functionality, but just for completeness, 00076 * they're here too, and will give the basic data needed... 00077 */ 00078 00079 /* poll callback for adding default KeyingSet */ 00080 static int keyingset_poll_default_add (bContext *C) 00081 { 00082 /* as long as there's an active Scene, it's fine */ 00083 return (CTX_data_scene(C) != NULL); 00084 } 00085 00086 /* poll callback for editing active KeyingSet */ 00087 static int keyingset_poll_active_edit (bContext *C) 00088 { 00089 Scene *scene= CTX_data_scene(C); 00090 00091 if (scene == NULL) 00092 return 0; 00093 00094 /* there must be an active KeyingSet (and KeyingSets) */ 00095 return ((scene->active_keyingset > 0) && (scene->keyingsets.first)); 00096 } 00097 00098 /* poll callback for editing active KeyingSet Path */ 00099 static int keyingset_poll_activePath_edit (bContext *C) 00100 { 00101 Scene *scene= CTX_data_scene(C); 00102 KeyingSet *ks; 00103 00104 if (scene == NULL) 00105 return 0; 00106 if (scene->active_keyingset <= 0) 00107 return 0; 00108 else 00109 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 00110 00111 /* there must be an active KeyingSet and an active path */ 00112 return ((ks) && (ks->paths.first) && (ks->active_path > 0)); 00113 } 00114 00115 00116 /* Add a Default (Empty) Keying Set ------------------------- */ 00117 00118 static int add_default_keyingset_exec (bContext *C, wmOperator *UNUSED(op)) 00119 { 00120 Scene *scene= CTX_data_scene(C); 00121 short flag=0, keyingflag=0; 00122 00123 /* validate flags 00124 * - absolute KeyingSets should be created by default 00125 */ 00126 flag |= KEYINGSET_ABSOLUTE; 00127 00128 /* 2nd arg is 0 to indicate that we don't want to include autokeying mode related settings */ 00129 keyingflag = ANIM_get_keyframing_flags(scene, 0); 00130 00131 /* call the API func, and set the active keyingset index */ 00132 BKE_keyingset_add(&scene->keyingsets, NULL, flag, keyingflag); 00133 00134 scene->active_keyingset= BLI_countlist(&scene->keyingsets); 00135 00136 /* send notifiers */ 00137 WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL); 00138 00139 return OPERATOR_FINISHED; 00140 } 00141 00142 void ANIM_OT_keying_set_add (wmOperatorType *ot) 00143 { 00144 /* identifiers */ 00145 ot->name= "Add Empty Keying Set"; 00146 ot->idname= "ANIM_OT_keying_set_add"; 00147 ot->description= "Add a new (empty) Keying Set to the active Scene"; 00148 00149 /* callbacks */ 00150 ot->exec= add_default_keyingset_exec; 00151 ot->poll= keyingset_poll_default_add; 00152 } 00153 00154 /* Remove 'Active' Keying Set ------------------------- */ 00155 00156 static int remove_active_keyingset_exec (bContext *C, wmOperator *op) 00157 { 00158 Scene *scene= CTX_data_scene(C); 00159 KeyingSet *ks; 00160 00161 /* verify the Keying Set to use: 00162 * - use the active one 00163 * - return error if it doesn't exist 00164 */ 00165 if (scene->active_keyingset == 0) { 00166 BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove"); 00167 return OPERATOR_CANCELLED; 00168 } 00169 else if (scene->active_keyingset < 0) { 00170 BKE_report(op->reports, RPT_ERROR, "Cannot remove built in Keying Set"); 00171 return OPERATOR_CANCELLED; 00172 } 00173 else 00174 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 00175 00176 /* free KeyingSet's data, then remove it from the scene */ 00177 BKE_keyingset_free(ks); 00178 BLI_freelinkN(&scene->keyingsets, ks); 00179 00180 /* the active one should now be the previously second-to-last one */ 00181 scene->active_keyingset--; 00182 00183 /* send notifiers */ 00184 WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL); 00185 00186 return OPERATOR_FINISHED; 00187 } 00188 00189 void ANIM_OT_keying_set_remove (wmOperatorType *ot) 00190 { 00191 /* identifiers */ 00192 ot->name= "Removed Active Keying Set"; 00193 ot->idname= "ANIM_OT_keying_set_remove"; 00194 ot->description= "Remove the active Keying Set"; 00195 00196 /* callbacks */ 00197 ot->exec= remove_active_keyingset_exec; 00198 ot->poll= keyingset_poll_active_edit; 00199 } 00200 00201 /* Add Empty Keying Set Path ------------------------- */ 00202 00203 static int add_empty_ks_path_exec (bContext *C, wmOperator *op) 00204 { 00205 Scene *scene= CTX_data_scene(C); 00206 KeyingSet *ks; 00207 KS_Path *ksp; 00208 00209 /* verify the Keying Set to use: 00210 * - use the active one 00211 * - return error if it doesn't exist 00212 */ 00213 if (scene->active_keyingset == 0) { 00214 BKE_report(op->reports, RPT_ERROR, "No active Keying Set to add empty path to"); 00215 return OPERATOR_CANCELLED; 00216 } 00217 else 00218 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 00219 00220 /* don't use the API method for this, since that checks on values... */ 00221 ksp= MEM_callocN(sizeof(KS_Path), "KeyingSetPath Empty"); 00222 BLI_addtail(&ks->paths, ksp); 00223 ks->active_path= BLI_countlist(&ks->paths); 00224 00225 ksp->groupmode= KSP_GROUP_KSNAME; // XXX? 00226 ksp->idtype= ID_OB; 00227 00228 return OPERATOR_FINISHED; 00229 } 00230 00231 void ANIM_OT_keying_set_path_add (wmOperatorType *ot) 00232 { 00233 /* identifiers */ 00234 ot->name= "Add Empty Keying Set Path"; 00235 ot->idname= "ANIM_OT_keying_set_path_add"; 00236 ot->description= "Add empty path to active Keying Set"; 00237 00238 /* callbacks */ 00239 ot->exec= add_empty_ks_path_exec; 00240 ot->poll= keyingset_poll_active_edit; 00241 } 00242 00243 /* Remove Active Keying Set Path ------------------------- */ 00244 00245 static int remove_active_ks_path_exec (bContext *C, wmOperator *op) 00246 { 00247 Scene *scene= CTX_data_scene(C); 00248 KeyingSet *ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 00249 00250 /* if there is a KeyingSet, find the nominated path to remove */ 00251 if (ks) { 00252 KS_Path *ksp= BLI_findlink(&ks->paths, ks->active_path-1); 00253 00254 if (ksp) { 00255 /* remove the active path from the KeyingSet */ 00256 BKE_keyingset_free_path(ks, ksp); 00257 00258 /* the active path should now be the previously second-to-last active one */ 00259 ks->active_path--; 00260 } 00261 else { 00262 BKE_report(op->reports, RPT_ERROR, "No active Keying Set Path to remove"); 00263 return OPERATOR_CANCELLED; 00264 } 00265 } 00266 else { 00267 BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove a path from"); 00268 return OPERATOR_CANCELLED; 00269 } 00270 00271 return OPERATOR_FINISHED; 00272 } 00273 00274 void ANIM_OT_keying_set_path_remove (wmOperatorType *ot) 00275 { 00276 /* identifiers */ 00277 ot->name= "Remove Active Keying Set Path"; 00278 ot->idname= "ANIM_OT_keying_set_path_remove"; 00279 ot->description= "Remove active Path from active Keying Set"; 00280 00281 /* callbacks */ 00282 ot->exec= remove_active_ks_path_exec; 00283 ot->poll= keyingset_poll_activePath_edit; 00284 } 00285 00286 /* ************************************************** */ 00287 /* KEYING SETS - OPERATORS (for use in UI menus) */ 00288 00289 /* Add to KeyingSet Button Operator ------------------------ */ 00290 00291 static int add_keyingset_button_exec (bContext *C, wmOperator *op) 00292 { 00293 Main *bmain= CTX_data_main(C); 00294 Scene *scene= CTX_data_scene(C); 00295 KeyingSet *ks = NULL; 00296 PropertyRNA *prop= NULL; 00297 PointerRNA ptr= {{NULL}}; 00298 char *path = NULL; 00299 short success= 0; 00300 int index=0, pflag=0; 00301 int all= RNA_boolean_get(op->ptr, "all"); 00302 00303 /* verify the Keying Set to use: 00304 * - use the active one for now (more control over this can be added later) 00305 * - add a new one if it doesn't exist 00306 */ 00307 if (scene->active_keyingset == 0) { 00308 short flag=0, keyingflag=0; 00309 00310 /* validate flags 00311 * - absolute KeyingSets should be created by default 00312 */ 00313 flag |= KEYINGSET_ABSOLUTE; 00314 00315 keyingflag |= ANIM_get_keyframing_flags(scene, 0); 00316 00317 if (IS_AUTOKEY_FLAG(scene, XYZ2RGB)) 00318 keyingflag |= INSERTKEY_XYZ2RGB; 00319 00320 /* call the API func, and set the active keyingset index */ 00321 ks= BKE_keyingset_add(&scene->keyingsets, "ButtonKeyingSet", flag, keyingflag); 00322 00323 scene->active_keyingset= BLI_countlist(&scene->keyingsets); 00324 } 00325 else if (scene->active_keyingset < 0) { 00326 BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in Keying Set"); 00327 return OPERATOR_CANCELLED; 00328 } 00329 else 00330 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 00331 00332 /* try to add to keyingset using property retrieved from UI */ 00333 uiContextActiveProperty(C, &ptr, &prop, &index); 00334 00335 /* check if property is able to be added */ 00336 if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { 00337 path= RNA_path_from_ID_to_property(&ptr, prop); 00338 00339 if (path) { 00340 /* set flags */ 00341 if (all) { 00342 pflag |= KSP_FLAG_WHOLE_ARRAY; 00343 00344 /* we need to set the index for this to 0, even though it may break in some cases, this is 00345 * necessary if we want the entire array for most cases to get included without the user 00346 * having to worry about where they clicked 00347 */ 00348 index= 0; 00349 } 00350 00351 /* add path to this setting */ 00352 BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME); 00353 ks->active_path= BLI_countlist(&ks->paths); 00354 success= 1; 00355 00356 /* free the temp path created */ 00357 MEM_freeN(path); 00358 } 00359 } 00360 00361 if (success) { 00362 /* send updates */ 00363 DAG_ids_flush_update(bmain, 0); 00364 00365 /* for now, only send ND_KEYS for KeyingSets */ 00366 WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL); 00367 } 00368 00369 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; 00370 } 00371 00372 void ANIM_OT_keyingset_button_add (wmOperatorType *ot) 00373 { 00374 /* identifiers */ 00375 ot->name= "Add to Keying Set"; 00376 ot->idname= "ANIM_OT_keyingset_button_add"; 00377 00378 /* callbacks */ 00379 ot->exec= add_keyingset_button_exec; 00380 //op->poll= ??? 00381 00382 /* flags */ 00383 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00384 00385 /* properties */ 00386 RNA_def_boolean(ot->srna, "all", 1, "All", "Add all elements of the array to a Keying Set."); 00387 } 00388 00389 /* Remove from KeyingSet Button Operator ------------------------ */ 00390 00391 static int remove_keyingset_button_exec (bContext *C, wmOperator *op) 00392 { 00393 Main *bmain= CTX_data_main(C); 00394 Scene *scene= CTX_data_scene(C); 00395 KeyingSet *ks = NULL; 00396 PropertyRNA *prop= NULL; 00397 PointerRNA ptr= {{NULL}}; 00398 char *path = NULL; 00399 short success= 0; 00400 int index=0; 00401 00402 /* verify the Keying Set to use: 00403 * - use the active one for now (more control over this can be added later) 00404 * - return error if it doesn't exist 00405 */ 00406 if (scene->active_keyingset == 0) { 00407 BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove property from"); 00408 return OPERATOR_CANCELLED; 00409 } 00410 else if (scene->active_keyingset < 0) { 00411 BKE_report(op->reports, RPT_ERROR, "Cannot remove property from built in Keying Set"); 00412 return OPERATOR_CANCELLED; 00413 } 00414 else 00415 ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 00416 00417 /* try to add to keyingset using property retrieved from UI */ 00418 uiContextActiveProperty(C, &ptr, &prop, &index); 00419 00420 if (ptr.id.data && ptr.data && prop) { 00421 path= RNA_path_from_ID_to_property(&ptr, prop); 00422 00423 if (path) { 00424 KS_Path *ksp; 00425 00426 /* try to find a path matching this description */ 00427 ksp= BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME); 00428 00429 if (ksp) { 00430 BKE_keyingset_free_path(ks, ksp); 00431 success= 1; 00432 } 00433 00434 /* free temp path used */ 00435 MEM_freeN(path); 00436 } 00437 } 00438 00439 00440 if (success) { 00441 /* send updates */ 00442 DAG_ids_flush_update(bmain, 0); 00443 00444 /* for now, only send ND_KEYS for KeyingSets */ 00445 WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL); 00446 } 00447 00448 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; 00449 } 00450 00451 void ANIM_OT_keyingset_button_remove (wmOperatorType *ot) 00452 { 00453 /* identifiers */ 00454 ot->name= "Remove from Keying Set"; 00455 ot->idname= "ANIM_OT_keyingset_button_remove"; 00456 00457 /* callbacks */ 00458 ot->exec= remove_keyingset_button_exec; 00459 //op->poll= ??? 00460 00461 /* flags */ 00462 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00463 } 00464 00465 /* ******************************************* */ 00466 00467 /* Change Active KeyingSet Operator ------------------------ */ 00468 /* This operator checks if a menu should be shown for choosing the KeyingSet to make the active one */ 00469 00470 static int keyingset_active_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00471 { 00472 /* call the menu, which will call this operator again, hence the cancelled */ 00473 ANIM_keying_sets_menu_setup(C, op->type->name, "ANIM_OT_keying_set_active_set"); 00474 return OPERATOR_CANCELLED; 00475 } 00476 00477 static int keyingset_active_menu_exec (bContext *C, wmOperator *op) 00478 { 00479 Scene *scene= CTX_data_scene(C); 00480 int type= RNA_int_get(op->ptr, "type"); 00481 00482 /* simply set the scene's active keying set index, unless the type == 0 00483 * (i.e. which happens if we want the current active to be maintained) 00484 */ 00485 if (type) 00486 scene->active_keyingset= type; 00487 00488 /* send notifiers */ 00489 WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL); 00490 00491 return OPERATOR_FINISHED; 00492 } 00493 00494 void ANIM_OT_keying_set_active_set (wmOperatorType *ot) 00495 { 00496 /* identifiers */ 00497 ot->name= "Set Active Keying Set"; 00498 ot->idname= "ANIM_OT_keying_set_active_set"; 00499 00500 /* callbacks */ 00501 ot->invoke= keyingset_active_menu_invoke; 00502 ot->exec= keyingset_active_menu_exec; 00503 ot->poll= ED_operator_areaactive; 00504 00505 /* flags */ 00506 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00507 00508 /* keyingset to use 00509 * - here the type is int not enum, since many of the indices here are determined dynamically 00510 */ 00511 RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); 00512 } 00513 00514 /* ******************************************* */ 00515 /* REGISTERED KEYING SETS */ 00516 00517 /* Keying Set Type Info declarations */ 00518 static ListBase keyingset_type_infos = {NULL, NULL}; 00519 00520 /* Built-In Keying Sets (referencing type infos)*/ 00521 ListBase builtin_keyingsets = {NULL, NULL}; 00522 00523 /* --------------- */ 00524 00525 /* Find KeyingSet type info given a name */ 00526 KeyingSetInfo *ANIM_keyingset_info_find_named (const char name[]) 00527 { 00528 /* sanity checks */ 00529 if ((name == NULL) || (name[0] == 0)) 00530 return NULL; 00531 00532 /* search by comparing names */ 00533 return BLI_findstring(&keyingset_type_infos, name, offsetof(KeyingSetInfo, idname)); 00534 } 00535 00536 /* Find builtin KeyingSet by name */ 00537 KeyingSet *ANIM_builtin_keyingset_get_named (KeyingSet *prevKS, const char name[]) 00538 { 00539 KeyingSet *ks, *first=NULL; 00540 00541 /* sanity checks any name to check? */ 00542 if (name[0] == 0) 00543 return NULL; 00544 00545 /* get first KeyingSet to use */ 00546 if (prevKS && prevKS->next) 00547 first= prevKS->next; 00548 else 00549 first= builtin_keyingsets.first; 00550 00551 /* loop over KeyingSets checking names */ 00552 for (ks= first; ks; ks= ks->next) { 00553 if (strcmp(name, ks->name) == 0) 00554 return ks; 00555 } 00556 00557 /* no matches found */ 00558 return NULL; 00559 } 00560 00561 /* --------------- */ 00562 00563 /* Add the given KeyingSetInfo to the list of type infos, and create an appropriate builtin set too */ 00564 void ANIM_keyingset_info_register (KeyingSetInfo *ksi) 00565 { 00566 KeyingSet *ks; 00567 00568 /* create a new KeyingSet 00569 * - inherit name and keyframing settings from the typeinfo 00570 */ 00571 ks = BKE_keyingset_add(&builtin_keyingsets, ksi->name, 1, ksi->keyingflag); 00572 00573 /* link this KeyingSet with its typeinfo */ 00574 memcpy(&ks->typeinfo, ksi->idname, sizeof(ks->typeinfo)); 00575 00576 /* add type-info to the list */ 00577 BLI_addtail(&keyingset_type_infos, ksi); 00578 } 00579 00580 /* Remove the given KeyingSetInfo from the list of type infos, and also remove the builtin set if appropriate */ 00581 void ANIM_keyingset_info_unregister (Main *bmain, KeyingSetInfo *ksi) 00582 { 00583 KeyingSet *ks, *ksn; 00584 00585 /* find relevant builtin KeyingSets which use this, and remove them */ 00586 // TODO: this isn't done now, since unregister is really only used atm when we 00587 // reload the scripts, which kindof defeats the purpose of "builtin"? 00588 for (ks= builtin_keyingsets.first; ks; ks= ksn) { 00589 ksn = ks->next; 00590 00591 /* remove if matching typeinfo name */ 00592 if (strcmp(ks->typeinfo, ksi->idname) == 0) { 00593 Scene *scene; 00594 BKE_keyingset_free(ks); 00595 BLI_remlink(&builtin_keyingsets, ks); 00596 00597 for(scene= bmain->scene.first; scene; scene= scene->id.next) 00598 BLI_remlink_safe(&scene->keyingsets, ks); 00599 00600 MEM_freeN(ks); 00601 } 00602 } 00603 00604 /* free the type info */ 00605 BLI_freelinkN(&keyingset_type_infos, ksi); 00606 } 00607 00608 /* --------------- */ 00609 00610 void ANIM_keyingset_infos_exit (void) 00611 { 00612 KeyingSetInfo *ksi, *next; 00613 00614 /* free type infos */ 00615 for (ksi=keyingset_type_infos.first; ksi; ksi=next) { 00616 next= ksi->next; 00617 00618 /* free extra RNA data, and remove from list */ 00619 if (ksi->ext.free) 00620 ksi->ext.free(ksi->ext.data); 00621 BLI_freelinkN(&keyingset_type_infos, ksi); 00622 } 00623 00624 /* free builtin sets */ 00625 BKE_keyingsets_free(&builtin_keyingsets); 00626 } 00627 00628 /* ******************************************* */ 00629 /* KEYING SETS API (for UI) */ 00630 00631 /* Getters for Active/Indices ----------------------------- */ 00632 00633 /* Get the active Keying Set for the Scene provided */ 00634 KeyingSet *ANIM_scene_get_active_keyingset (Scene *scene) 00635 { 00636 /* if no scene, we've got no hope of finding the Keying Set */ 00637 if (scene == NULL) 00638 return NULL; 00639 00640 /* currently, there are several possibilities here: 00641 * - 0: no active keying set 00642 * - > 0: one of the user-defined Keying Sets, but indices start from 0 (hence the -1) 00643 * - < 0: a builtin keying set 00644 */ 00645 if (scene->active_keyingset > 0) 00646 return BLI_findlink(&scene->keyingsets, scene->active_keyingset-1); 00647 else 00648 return BLI_findlink(&builtin_keyingsets, (-scene->active_keyingset)-1); 00649 } 00650 00651 /* Get the index of the Keying Set provided, for the given Scene */ 00652 int ANIM_scene_get_keyingset_index (Scene *scene, KeyingSet *ks) 00653 { 00654 int index; 00655 00656 /* if no KeyingSet provided, have none */ 00657 if (ks == NULL) 00658 return 0; 00659 00660 /* check if the KeyingSet exists in scene list */ 00661 if (scene) { 00662 /* get index and if valid, return 00663 * - (absolute) Scene KeyingSets are from (>= 1) 00664 */ 00665 index = BLI_findindex(&scene->keyingsets, ks); 00666 if (index != -1) 00667 return (index + 1); 00668 } 00669 00670 /* still here, so try builtins list too 00671 * - builtins are from (<= -1) 00672 * - none/invalid is (= 0) 00673 */ 00674 index = BLI_findindex(&builtin_keyingsets, ks); 00675 if (index != -1) 00676 return -(index + 1); 00677 else 00678 return 0; 00679 } 00680 00681 /* Get Keying Set to use for Auto-Keyframing some transforms */ 00682 KeyingSet *ANIM_get_keyingset_for_autokeying(Scene *scene, const char *tranformKSName) 00683 { 00684 /* get KeyingSet to use 00685 * - use the active KeyingSet if defined (and user wants to use it for all autokeying), 00686 * or otherwise key transforms only 00687 */ 00688 if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (scene->active_keyingset)) 00689 return ANIM_scene_get_active_keyingset(scene); 00690 else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) 00691 return ANIM_builtin_keyingset_get_named(NULL, "Available"); 00692 else 00693 return ANIM_builtin_keyingset_get_named(NULL, tranformKSName); 00694 } 00695 00696 /* Menu of All Keying Sets ----------------------------- */ 00697 00698 /* Dynamically populate an enum of Keying Sets */ 00699 EnumPropertyItem *ANIM_keying_sets_enum_itemf (bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) 00700 { 00701 Scene *scene = CTX_data_scene(C); 00702 KeyingSet *ks; 00703 EnumPropertyItem *item= NULL, item_tmp= {0}; 00704 int totitem= 0; 00705 int i= 0; 00706 00707 if (C == NULL) { 00708 return DummyRNA_DEFAULT_items; 00709 } 00710 00711 /* active Keying Set 00712 * - only include entry if it exists 00713 */ 00714 if (scene->active_keyingset) { 00715 /* active Keying Set */ 00716 item_tmp.identifier= item_tmp.name= "Active Keying Set"; 00717 item_tmp.value= i++; 00718 RNA_enum_item_add(&item, &totitem, &item_tmp); 00719 00720 /* separator */ 00721 RNA_enum_item_add_separator(&item, &totitem); 00722 } 00723 else 00724 i++; 00725 00726 /* user-defined Keying Sets 00727 * - these are listed in the order in which they were defined for the active scene 00728 */ 00729 if (scene->keyingsets.first) { 00730 for (ks= scene->keyingsets.first; ks; ks= ks->next) { 00731 if (ANIM_keyingset_context_ok_poll(C, ks)) { 00732 item_tmp.identifier= item_tmp.name= ks->name; 00733 item_tmp.value= i++; 00734 RNA_enum_item_add(&item, &totitem, &item_tmp); 00735 } 00736 } 00737 00738 /* separator */ 00739 RNA_enum_item_add_separator(&item, &totitem); 00740 } 00741 00742 /* builtin Keying Sets */ 00743 i= -1; 00744 for (ks= builtin_keyingsets.first; ks; ks= ks->next) { 00745 /* only show KeyingSet if context is suitable */ 00746 if (ANIM_keyingset_context_ok_poll(C, ks)) { 00747 item_tmp.identifier= item_tmp.name= ks->name; 00748 item_tmp.value= i--; 00749 RNA_enum_item_add(&item, &totitem, &item_tmp); 00750 } 00751 } 00752 00753 RNA_enum_item_end(&item, &totitem); 00754 *free= 1; 00755 00756 return item; 00757 } 00758 00759 /* Create (and show) a menu containing all the Keying Sets which can be used in the current context */ 00760 void ANIM_keying_sets_menu_setup (bContext *C, const char title[], const char op_name[]) 00761 { 00762 Scene *scene= CTX_data_scene(C); 00763 KeyingSet *ks; 00764 uiPopupMenu *pup; 00765 uiLayout *layout; 00766 int i = 0; 00767 00768 pup= uiPupMenuBegin(C, title, ICON_NONE); 00769 layout= uiPupMenuLayout(pup); 00770 00771 /* active Keying Set 00772 * - only include entry if it exists 00773 */ 00774 if (scene->active_keyingset) { 00775 uiItemIntO(layout, "Active Keying Set", ICON_NONE, op_name, "type", i++); 00776 uiItemS(layout); 00777 } 00778 else 00779 i++; 00780 00781 /* user-defined Keying Sets 00782 * - these are listed in the order in which they were defined for the active scene 00783 */ 00784 if (scene->keyingsets.first) { 00785 for (ks= scene->keyingsets.first; ks; ks= ks->next) { 00786 if (ANIM_keyingset_context_ok_poll(C, ks)) 00787 uiItemIntO(layout, ks->name, ICON_NONE, op_name, "type", i++); 00788 } 00789 uiItemS(layout); 00790 } 00791 00792 /* builtin Keying Sets */ 00793 i= -1; 00794 for (ks= builtin_keyingsets.first; ks; ks= ks->next) { 00795 /* only show KeyingSet if context is suitable */ 00796 if (ANIM_keyingset_context_ok_poll(C, ks)) 00797 uiItemEnumO_value(layout, ks->name, ICON_NONE, op_name, "type", i--); 00798 } 00799 00800 uiPupMenuEnd(C, pup); 00801 } 00802 00803 /* ******************************************* */ 00804 /* KEYFRAME MODIFICATION */ 00805 00806 /* Polling API ----------------------------------------------- */ 00807 00808 /* Check if KeyingSet can be used in the current context */ 00809 short ANIM_keyingset_context_ok_poll (bContext *C, KeyingSet *ks) 00810 { 00811 if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) { 00812 KeyingSetInfo *ksi = ANIM_keyingset_info_find_named(ks->typeinfo); 00813 00814 /* get the associated 'type info' for this KeyingSet */ 00815 if (ksi == NULL) 00816 return 0; 00817 // TODO: check for missing callbacks! 00818 00819 /* check if it can be used in the current context */ 00820 return (ksi->poll(ksi, C)); 00821 } 00822 00823 return 1; 00824 } 00825 00826 /* Special 'Overrides' Iterator for Relative KeyingSets ------ */ 00827 00828 /* 'Data Sources' for relative Keying Set 'overrides' 00829 * - this is basically a wrapper for PointerRNA's in a linked list 00830 * - do not allow this to be accessed from outside for now 00831 */ 00832 typedef struct tRKS_DSource { 00833 struct tRKS_DSource *next, *prev; 00834 PointerRNA ptr; /* the whole point of this exercise! */ 00835 } tRKS_DSource; 00836 00837 00838 /* Iterator used for overriding the behaviour of iterators defined for 00839 * relative Keying Sets, with the main usage of this being operators 00840 * requiring Auto Keyframing. Internal Use Only! 00841 */ 00842 static void RKS_ITER_overrides_list (KeyingSetInfo *ksi, bContext *C, KeyingSet *ks, ListBase *dsources) 00843 { 00844 tRKS_DSource *ds; 00845 00846 for (ds = dsources->first; ds; ds = ds->next) { 00847 /* run generate callback on this data */ 00848 ksi->generate(ksi, C, ks, &ds->ptr); 00849 } 00850 } 00851 00852 /* Add new data source for relative Keying Sets */ 00853 void ANIM_relative_keyingset_add_source (ListBase *dsources, ID *id, StructRNA *srna, void *data) 00854 { 00855 tRKS_DSource *ds; 00856 00857 /* sanity checks 00858 * - we must have somewhere to output the data 00859 * - we must have both srna+data (and with id too optionally), or id by itself only 00860 */ 00861 if (dsources == NULL) 00862 return; 00863 if (ELEM(NULL, srna, data) && (id == NULL)) 00864 return; 00865 00866 /* allocate new elem, and add to the list */ 00867 ds = MEM_callocN(sizeof(tRKS_DSource), "tRKS_DSource"); 00868 BLI_addtail(dsources, ds); 00869 00870 /* depending on what data we have, create using ID or full pointer call */ 00871 if (srna && data) 00872 RNA_pointer_create(id, srna, data, &ds->ptr); 00873 else 00874 RNA_id_pointer_create(id, &ds->ptr); 00875 } 00876 00877 /* KeyingSet Operations (Insert/Delete Keyframes) ------------ */ 00878 00879 /* Given a KeyingSet and context info (if required), modify keyframes for the channels specified 00880 * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets. 00881 * Returns the number of channels that keyframes were added to 00882 */ 00883 int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra) 00884 { 00885 Scene *scene= CTX_data_scene(C); 00886 ReportList *reports = CTX_wm_reports(C); 00887 KS_Path *ksp; 00888 int kflag=0, success= 0; 00889 char *groupname= NULL; 00890 00891 /* sanity checks */ 00892 if (ks == NULL) 00893 return 0; 00894 00895 /* get flags to use */ 00896 if (mode == MODIFYKEY_MODE_INSERT) { 00897 /* use KeyingSet's flags as base */ 00898 kflag= ks->keyingflag; 00899 00900 /* suppliment with info from the context */ 00901 kflag |= ANIM_get_keyframing_flags(scene, 1); 00902 } 00903 else if (mode == MODIFYKEY_MODE_DELETE) 00904 kflag= 0; 00905 00906 /* if relative Keying Sets, poll and build up the paths */ 00907 if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) { 00908 KeyingSetInfo *ksi = ANIM_keyingset_info_find_named(ks->typeinfo); 00909 00910 /* clear all existing paths 00911 * NOTE: BKE_keyingset_free() frees all of the paths for the KeyingSet, but not the set itself 00912 */ 00913 BKE_keyingset_free(ks); 00914 00915 /* get the associated 'type info' for this KeyingSet */ 00916 if (ksi == NULL) 00917 return MODIFYKEY_MISSING_TYPEINFO; 00918 // TODO: check for missing callbacks! 00919 00920 /* check if it can be used in the current context */ 00921 if (ksi->poll(ksi, C)) { 00922 /* if a list of data sources are provided, run a special iterator over them, 00923 * otherwise, just continue per normal 00924 */ 00925 if (dsources) 00926 RKS_ITER_overrides_list(ksi, C, ks, dsources); 00927 else 00928 ksi->iter(ksi, C, ks); 00929 00930 /* if we don't have any paths now, then this still qualifies as invalid context */ 00931 if (ks->paths.first == NULL) 00932 return MODIFYKEY_INVALID_CONTEXT; 00933 } 00934 else { 00935 /* poll callback tells us that KeyingSet is useless in current context */ 00936 return MODIFYKEY_INVALID_CONTEXT; 00937 } 00938 } 00939 00940 /* apply the paths as specified in the KeyingSet now */ 00941 for (ksp= ks->paths.first; ksp; ksp= ksp->next) { 00942 int arraylen, i; 00943 short kflag2; 00944 00945 /* skip path if no ID pointer is specified */ 00946 if (ksp->id == NULL) { 00947 BKE_reportf(reports, RPT_WARNING, 00948 "Skipping path in Keying Set, as it has no ID (KS = '%s', Path = '%s'[%d])", 00949 ks->name, ksp->rna_path, ksp->array_index); 00950 continue; 00951 } 00952 00953 /* since keying settings can be defined on the paths too, extend the path before using it */ 00954 kflag2 = (kflag | ksp->keyingflag); 00955 00956 /* get pointer to name of group to add channels to */ 00957 if (ksp->groupmode == KSP_GROUP_NONE) 00958 groupname= NULL; 00959 else if (ksp->groupmode == KSP_GROUP_KSNAME) 00960 groupname= ks->name; 00961 else 00962 groupname= ksp->group; 00963 00964 /* init arraylen and i - arraylen should be greater than i so that 00965 * normal non-array entries get keyframed correctly 00966 */ 00967 i= ksp->array_index; 00968 arraylen= i; 00969 00970 /* get length of array if whole array option is enabled */ 00971 if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) { 00972 PointerRNA id_ptr, ptr; 00973 PropertyRNA *prop; 00974 00975 RNA_id_pointer_create(ksp->id, &id_ptr); 00976 if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop) 00977 arraylen= RNA_property_array_length(&ptr, prop); 00978 } 00979 00980 /* we should do at least one step */ 00981 if (arraylen == i) 00982 arraylen++; 00983 00984 /* for each possible index, perform operation 00985 * - assume that arraylen is greater than index 00986 */ 00987 for (; i < arraylen; i++) { 00988 /* action to take depends on mode */ 00989 if (mode == MODIFYKEY_MODE_INSERT) 00990 success += insert_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); 00991 else if (mode == MODIFYKEY_MODE_DELETE) 00992 success += delete_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2); 00993 } 00994 00995 /* set recalc-flags */ 00996 switch (GS(ksp->id->name)) { 00997 case ID_OB: /* Object (or Object-Related) Keyframes */ 00998 { 00999 Object *ob= (Object *)ksp->id; 01000 01001 ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; // XXX: only object transforms only? 01002 } 01003 break; 01004 } 01005 01006 /* send notifiers for updates (this doesn't require context to work!) */ 01007 WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); 01008 } 01009 01010 /* return the number of channels successfully affected */ 01011 return success; 01012 } 01013 01014 /* ************************************************** */