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