diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-04-10 17:08:12 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-04-10 17:08:12 +0400 |
commit | 6593bbaca2ceb248426c55e14ceb21bb46553fd1 (patch) | |
tree | 9e778b12484bd6d03c349bcebae4219076c7d09a /source/blender | |
parent | be8b7ead51a5efb5dbd762075ee52812465ba8d6 (diff) |
2.5 - Groundwork for Adding/Removing Drivers
Drivers can now be Added/Removed from buttons using the D/Alt-D hotkeys, and also through the menu. Driver settings (i.e. the target) are not set by default. To set those, go to the Graph Editor (see notes).
Notes:
* Buildsystem maintainers - I've added a new file "editors/animation/drivers.c"
* Widget colours for the driven-setting indications are needed
* To see the new drivers, go into Graph Editor -> "Drivers" mode. Currently, there's a little bug there which prevents editing of the new drivers.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/animation/anim_ops.c | 3 | ||||
-rw-r--r-- | source/blender/editors/animation/drivers.c | 289 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 2 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframing.h | 17 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_anim.c | 66 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 11 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 2 |
9 files changed, 376 insertions, 17 deletions
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index b7a59822e71..e899cc1d520 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -386,6 +386,9 @@ void ED_operatortypes_anim(void) WM_operatortype_append(ANIM_OT_delete_keyframe_button); WM_operatortype_append(ANIM_OT_delete_keyframe_old); // xxx remove? + WM_operatortype_append(ANIM_OT_add_driver_button); + WM_operatortype_append(ANIM_OT_remove_driver_button); + WM_operatortype_append(ANIM_OT_keyingset_add_new); WM_operatortype_append(ANIM_OT_keyingset_add_destination); } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c new file mode 100644 index 00000000000..15aad71f224 --- /dev/null +++ b/source/blender/editors/animation/drivers.c @@ -0,0 +1,289 @@ +/* Testing code for 2.5 animation system + * Copyright 2009, Joshua Leung + */ + +#include <stdio.h> +#include <stddef.h> +#include <string.h> +#include <math.h> +#include <float.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_dynstr.h" + +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_key_types.h" +#include "DNA_object_types.h" +#include "DNA_material_types.h" +#include "DNA_scene_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" + +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_constraint.h" +#include "BKE_fcurve.h" +#include "BKE_utildefines.h" +#include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_key.h" +#include "BKE_material.h" + +#include "ED_anim_api.h" +#include "ED_keyframing.h" +#include "ED_keyframes_edit.h" +#include "ED_screen.h" +#include "ED_util.h" + +#include "UI_interface.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_types.h" + +/* ************************************************** */ +/* Animation Data Validation */ + +/* Get (or add relevant data to be able to do so) F-Curve from the driver stack, + * for the given Animation Data block. This assumes that all the destinations are valid. + */ +FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add) +{ + AnimData *adt; + FCurve *fcu; + + /* sanity checks */ + if ELEM(NULL, id, rna_path) + return NULL; + + /* init animdata if none available yet */ + adt= BKE_animdata_from_id(id); + if ((adt == NULL) && (add)) + adt= BKE_id_add_animdata(id); + if (adt == NULL) { + /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ + return NULL; + } + + /* try to find f-curve matching for this setting + * - add if not found and allowed to add one + * TODO: add auto-grouping support? how this works will need to be resolved + */ + fcu= list_find_fcurve(&adt->drivers, rna_path, array_index); + + if ((fcu == NULL) && (add)) { + /* use default settings to make a F-Curve */ + fcu= MEM_callocN(sizeof(FCurve), "FCurve"); + + fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); + + /* store path - make copy, and store that */ + fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path)); + fcu->array_index= array_index; + + /* add some new driver data */ + fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); + + /* just add F-Curve to end of driver list */ + BLI_addtail(&adt->drivers, fcu); + } + + /* return the F-Curve */ + return fcu; +} + +/* ************************************************** */ +/* Driver Management API */ + +/* Main Driver Management API calls: + * Add a new driver for the specified property on the given ID block + */ +short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short flag) +{ + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + FCurve *fcu; + + /* validate pointer first - exit if failure */ + RNA_id_pointer_create(id, &id_ptr); + if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { + printf("Insert Key: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + return 0; + } + + /* create F-Curve with Driver */ + fcu= verify_driver_fcurve(id, rna_path, array_index, 1); + + /* done */ + return (fcu != NULL); +} + +/* Main Driver Management API calls: + * Remove the driver for the specified property on the given ID block (if available) + */ +short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag) +{ + AnimData *adt; + FCurve *fcu; + + /* get F-Curve + * Note: here is one of the places where we don't want new F-Curve + Driver added! + * so 'add' var must be 0 + */ + /* we don't check the validity of the path here yet, but it should be ok... */ + fcu= verify_driver_fcurve(id, rna_path, array_index, 0); + adt= BKE_animdata_from_id(id); + + /* only continue if we have an driver to remove */ + if (adt && fcu) { + /* remove F-Curve from driver stack, then free it */ + BLI_remlink(&adt->drivers, fcu); + free_fcurve(fcu); + + /* done successfully */ + return 1; + } + + /* failed */ + return 0; +} + + +/* ************************************************** */ +/* UI-Button Interface */ + +/* Add Driver Button Operator ------------------------ */ + +static int add_driver_button_exec (bContext *C, wmOperator *op) +{ + PointerRNA ptr; + PropertyRNA *prop= NULL; + char *path; + short success= 0; + int a, index, length, all= RNA_boolean_get(op->ptr, "all"); + + /* try to insert keyframe using property retrieved from UI */ + memset(&ptr, 0, sizeof(PointerRNA)); + uiAnimContextProperty(C, &ptr, &prop, &index); + + if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) { + path= RNA_path_from_ID_to_property(&ptr, prop); + + if (path) { + if (all) { + length= RNA_property_array_length(&ptr, prop); + + if (length) index= 0; + else length= 1; + } + else + length= 1; + + for (a=0; a<length; a++) + success+= ANIM_add_driver(ptr.id.data, path, index+a, 0); + + MEM_freeN(path); + } + } + + if (success) { + /* send updates */ + ED_anim_dag_flush_update(C); + + /* for now, only send ND_KEYS for KeyingSets */ + WM_event_add_notifier(C, ND_KEYS, NULL); // XXX + } + + return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; +} + +void ANIM_OT_add_driver_button (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Driver"; + ot->idname= "ANIM_OT_add_driver_button"; + + /* callbacks */ + ot->exec= add_driver_button_exec; + //op->poll= ??? + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "all", 1, "All", "Insert a keyframe for all element of the array."); +} + +/* Remove Driver Button Operator ------------------------ */ + +static int remove_driver_button_exec (bContext *C, wmOperator *op) +{ + PointerRNA ptr; + PropertyRNA *prop= NULL; + char *path; + short success= 0; + int a, index, length, all= RNA_boolean_get(op->ptr, "all"); + + /* try to insert keyframe using property retrieved from UI */ + memset(&ptr, 0, sizeof(PointerRNA)); + uiAnimContextProperty(C, &ptr, &prop, &index); + + if (ptr.data && prop) { + path= RNA_path_from_ID_to_property(&ptr, prop); + + if (path) { + if (all) { + length= RNA_property_array_length(&ptr, prop); + + if(length) index= 0; + else length= 1; + } + else + length= 1; + + for (a=0; a<length; a++) + success+= ANIM_remove_driver(ptr.id.data, path, index+a, 0); + + MEM_freeN(path); + } + } + + + if (success) { + /* send updates */ + ED_anim_dag_flush_update(C); + + /* for now, only send ND_KEYS for KeyingSets */ + WM_event_add_notifier(C, ND_KEYS, NULL); // XXX + } + + return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; +} + +void ANIM_OT_remove_driver_button (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Driver"; + ot->idname= "ANIM_OT_remove_driver_button"; + + /* callbacks */ + ot->exec= remove_driver_button_exec; + //op->poll= ??? + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyfames from all elements of the array."); +} + +/* ************************************************** */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index f6d23af932a..d87e61ae9ad 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -825,7 +825,7 @@ short deletekey (ID *id, const char group[], const char rna_path[], int array_in fcu= verify_fcurve(id, group, rna_path, array_index, 0); adt= BKE_animdata_from_id(id); - /* only continue if we have an ipo-curve to remove keyframes from */ + /* only continue if we have an F-Curve to remove keyframes from */ if (adt && adt->action && fcu) { bAction *act= adt->action; short found = -1; diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 5e4e0d4a44d..98a44d3ef2b 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -95,10 +95,25 @@ void ANIM_OT_delete_keyframe_menu(struct wmOperatorType *ot); // xxx unimplement void ANIM_OT_delete_keyframe_old(struct wmOperatorType *ot); // xxx rename and keep? /* Keyframe managment operators for UI buttons. */ - void ANIM_OT_insert_keyframe_button(struct wmOperatorType *ot); void ANIM_OT_delete_keyframe_button(struct wmOperatorType *ot); +/* ************ Drivers ********************** */ + +/* Main Driver Management API calls: + * Add a new driver for the specified property on the given ID block + */ +short ANIM_add_driver (struct ID *id, const char rna_path[], int array_index, short flag); + +/* Main Driver Management API calls: + * Remove the driver for the specified property on the given ID block (if available) + */ +short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag); + +/* Driver management operators for UI buttons */ +void ANIM_OT_add_driver_button(struct wmOperatorType *ot); +void ANIM_OT_remove_driver_button(struct wmOperatorType *ot); + /* ************ Auto-Keyframing ********************** */ /* Notes: * - All the defines for this (User-Pref settings and Per-Scene settings) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7c36f89cb41..9c8cba94fae 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -133,6 +133,7 @@ typedef struct uiPopupBlockHandle uiPopupBlockHandle; #define UI_NO_HILITE (1<<19) #define UI_BUT_ANIMATED (1<<20) #define UI_BUT_ANIMATED_KEY (1<<21) +#define UI_BUT_DRIVEN (1<<22) /* Button types, bits stored in 1 value... and a short even! diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 75fe8331184..3b89fbddebc 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -27,28 +27,41 @@ void ui_but_anim_flag(uiBut *but, float cfra) { - but->flag &= ~(UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY); + but->flag &= ~(UI_BUT_ANIMATED|UI_BUT_ANIMATED_KEY|UI_BUT_DRIVEN); if(but->rnaprop && but->rnapoin.id.data) { AnimData *adt= BKE_animdata_from_id(but->rnapoin.id.data); FCurve *fcu; char *path; - if(adt && adt->action && adt->action->curves.first) { - /* XXX this function call can become a performance bottleneck */ - path= RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop); - - if(path) { - fcu= list_find_fcurve(&adt->action->curves, path, but->rnaindex); - - if(fcu) { - but->flag |= UI_BUT_ANIMATED; - - if(on_keyframe_fcurve(fcu, cfra)) - but->flag |= UI_BUT_ANIMATED_KEY; + if (adt) { + if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) { + /* XXX this function call can become a performance bottleneck */ + path= RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop); + + if (path) { + /* animation takes priority over drivers */ + if (adt->action && adt->action->curves.first) { + fcu= list_find_fcurve(&adt->action->curves, path, but->rnaindex); + + if (fcu) { + but->flag |= UI_BUT_ANIMATED; + + if (on_keyframe_fcurve(fcu, cfra)) + but->flag |= UI_BUT_ANIMATED_KEY; + } + } + + /* if not animated, check if driven */ + if ((but->flag & UI_BUT_ANIMATED)==0 && (adt->drivers.first)) { + fcu= list_find_fcurve(&adt->drivers, path, but->rnaindex); + + if (fcu) + but->flag |= UI_BUT_DRIVEN; + } + + MEM_freeN(path); } - - MEM_freeN(path); } } } @@ -86,6 +99,19 @@ void ui_but_anim_delete_keyframe(bContext *C) WM_operator_name_call(C, "ANIM_OT_delete_keyframe_button", WM_OP_INVOKE_DEFAULT, NULL); } +void ui_but_anim_add_driver(bContext *C) +{ + /* this operator calls uiAnimContextProperty above */ + WM_operator_name_call(C, "ANIM_OT_add_driver_button", WM_OP_INVOKE_DEFAULT, NULL); +} + +void ui_but_anim_remove_driver(bContext *C) +{ + /* this operator calls uiAnimContextProperty above */ + WM_operator_name_call(C, "ANIM_OT_remove_driver_button", WM_OP_INVOKE_DEFAULT, NULL); +} + +// TODO: refine the logic for adding/removing drivers... void ui_but_anim_menu(bContext *C, uiBut *but) { uiMenuItem *head; @@ -100,18 +126,28 @@ void ui_but_anim_menu(bContext *C, uiBut *but) if(length) { uiMenuItemBooleanO(head, "Delete Keyframes", 0, "ANIM_OT_delete_keyframe_button", "all", 1); uiMenuItemBooleanO(head, "Delete Single Keyframe", 0, "ANIM_OT_delete_keyframe_button", "all", 0); + + uiMenuItemBooleanO(head, "Remove Driver", 0, "ANIM_OT_remove_driver_button", "all", 1); + uiMenuItemBooleanO(head, "Remove Single Driver", 0, "ANIM_OT_remove_driver_button", "all", 0); } else { uiMenuItemBooleanO(head, "Delete Keyframe", 0, "ANIM_OT_delete_keyframe_button", "all", 0); + + uiMenuItemBooleanO(head, "Remove Driver", 0, "ANIM_OT_remove_driver_button", "all", 0); } } else if(RNA_property_animateable(&but->rnapoin, but->rnaprop)) { if(length) { uiMenuItemBooleanO(head, "Insert Keyframes", 0, "ANIM_OT_insert_keyframe_button", "all", 1); uiMenuItemBooleanO(head, "Insert Single Keyframe", 0, "ANIM_OT_insert_keyframe_button", "all", 0); + + uiMenuItemBooleanO(head, "Add Driver", 0, "ANIM_OT_add_driver_button", "all", 1); + uiMenuItemBooleanO(head, "Add Single Driver", 0, "ANIM_OT_add_driver_button", "all", 0); } else { uiMenuItemBooleanO(head, "Insert Keyframe", 0, "ANIM_OT_insert_keyframe_button", "all", 0); + + uiMenuItemBooleanO(head, "Add Driver", 0, "ANIM_OT_add_driver_button", "all", 0); } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6fc0ad37ee3..b41fe7b9b7d 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2610,6 +2610,17 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) return WM_UI_HANDLER_BREAK; } + /* handle driver adding */ + else if(event->type == DKEY && event->val == KM_PRESS) { + if(event->alt) + ui_but_anim_remove_driver(C); + else + ui_but_anim_add_driver(C); + + ED_region_tag_redraw(CTX_wm_region(C)); + + return WM_UI_HANDLER_BREAK; + } /* handle menu */ else if(event->type == RIGHTMOUSE && event->val == KM_PRESS) { ui_but_anim_menu(C, but); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 2e975c871cf..8061d075e22 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -393,6 +393,8 @@ void uiStyleExit(void); void ui_but_anim_flag(uiBut *but, float cfra); void ui_but_anim_insert_keyframe(struct bContext *C); void ui_but_anim_delete_keyframe(struct bContext *C); +void ui_but_anim_add_driver(struct bContext *C); +void ui_but_anim_remove_driver(struct bContext *C); void ui_but_anim_menu(struct bContext *C, uiBut *but); #endif diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 958cde4efe4..d226ee4a45e 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1053,6 +1053,8 @@ static void widget_state(uiWidgetType *wt, int state) QUATCOPY(wt->wcol.inner, wt->wcol.inner_key_sel) else if(state & UI_BUT_ANIMATED) QUATCOPY(wt->wcol.inner, wt->wcol.inner_anim_sel) + //else if(state & UI_BUT_DRIVEN) + // QUATCOPY(wt->wcol.inner, wt->wcol.inner_driven_sel) else QUATCOPY(wt->wcol.inner, wt->wcol.inner_sel) |