Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/animation/anim_intern.h1
-rw-r--r--source/blender/editors/animation/anim_ops.c1
-rw-r--r--source/blender/editors/animation/keyframing.c157
-rw-r--r--source/blender/editors/interface/interface_anim.c6
-rw-r--r--source/blender/editors/interface/interface_handlers.c28
-rw-r--r--source/blender/editors/interface/interface_intern.h1
6 files changed, 190 insertions, 4 deletions
diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h
index 7d1209a3033..cf84eb04b10 100644
--- a/source/blender/editors/animation/anim_intern.h
+++ b/source/blender/editors/animation/anim_intern.h
@@ -55,6 +55,7 @@ void ANIM_OT_keyframe_delete_v3d(struct wmOperatorType *ot);
/* Keyframe managment operators for UI buttons (RMB menu). */
void ANIM_OT_keyframe_insert_button(struct wmOperatorType *ot);
void ANIM_OT_keyframe_delete_button(struct wmOperatorType *ot);
+void ANIM_OT_keyframe_clear_button(struct wmOperatorType *ot);
/* .......... */
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 119df33dd91..13741a99d99 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -294,6 +294,7 @@ void ED_operatortypes_anim(void)
WM_operatortype_append(ANIM_OT_keyframe_delete_v3d);
WM_operatortype_append(ANIM_OT_keyframe_insert_button);
WM_operatortype_append(ANIM_OT_keyframe_delete_button);
+ WM_operatortype_append(ANIM_OT_keyframe_clear_button);
WM_operatortype_append(ANIM_OT_driver_button_add);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 7600e1d4690..3ef686910e6 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1079,6 +1079,91 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
return ret;
}
+/* ************************************************** */
+/* KEYFRAME CLEAR */
+
+/* Main Keyframing API call:
+ * Use this when validation of necessary animation data isn't necessary as it
+ * already exists. It will clear the current buttons fcurve(s).
+ *
+ * The flag argument is used for special settings that alter the behavior of
+ * the keyframe deletion. These include the quick refresh options.
+ */
+short clear_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, short UNUSED(flag))
+{
+ AnimData *adt = BKE_animdata_from_id(id);
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ int array_index_max = array_index + 1;
+ int ret = 0;
+
+ /* sanity checks */
+ if (ELEM(NULL, id, adt)) {
+ BKE_report(reports, RPT_ERROR, "No ID-Block and/Or AnimData to delete keyframe from");
+ return 0;
+ }
+
+ /* 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)) {
+ BKE_reportf(reports, RPT_ERROR, "Could not clear keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", id->name, rna_path);
+ return 0;
+ }
+
+ /* get F-Curve
+ * Note: here is one of the places where we don't want new Action + F-Curve added!
+ * so 'add' var must be 0
+ */
+ if (act == NULL) {
+ /* if no action is provided, use the default one attached to this ID-block
+ * - if it doesn't exist, then we're out of options...
+ */
+ if (adt->action) {
+ act = adt->action;
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "No Action to delete keyframes from for ID = %s\n", id->name);
+ return 0;
+ }
+ }
+
+ /* key entire array convenience method */
+ if (array_index == -1) {
+ array_index = 0;
+ array_index_max = RNA_property_array_length(&ptr, prop);
+
+ /* for single properties, increase max_index so that the property itself gets included,
+ * but don't do this for standard arrays since that can cause corruption issues
+ * (extra unused curves)
+ */
+ if (array_index_max == array_index)
+ array_index_max++;
+ }
+
+ /* will only loop once unless the array index was -1 */
+ for (; array_index < array_index_max; array_index++) {
+ FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
+
+ /* check if F-Curve exists and/or whether it can be edited */
+ if (fcu == NULL)
+ continue;
+
+ if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
+ if (G.debug & G_DEBUG)
+ printf("WARNING: not deleting keyframe for locked F-Curve\n");
+ continue;
+ }
+
+ ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
+
+ /* return success */
+ ret++;
+ }
+
+ /* return success/failure */
+ return ret;
+}
+
/* ******************************************* */
/* KEYFRAME MODIFICATION */
@@ -1584,6 +1669,78 @@ void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 1, "All", "Delete keyframes from all elements of the array");
}
+
+/* Clear Key Button Operator ------------------------ */
+
+static int clear_key_button_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr = {{NULL}};
+ 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 */
+ uiContextActiveProperty(C, &ptr, &prop, &index);
+
+ if (ptr.id.data && 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 += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0);
+
+ MEM_freeN(path);
+ }
+ else if (G.debug & G_DEBUG)
+ printf("Button Clear-Key: no path to property\n");
+ }
+ else if (G.debug & G_DEBUG) {
+ printf("ptr.data = %p, prop = %p\n", (void *)ptr.data, (void *)prop);
+ }
+
+
+ if (success) {
+ /* send updates */
+ uiContextAnimUpdate(C);
+
+ DAG_ids_flush_update(bmain, 0);
+
+ /* send notifiers that keyframes have been changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
+ }
+
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+void ANIM_OT_keyframe_clear_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Keyframe (Buttons)";
+ ot->idname = "ANIM_OT_keyframe_clear_button";
+ ot->description = "Clear all keyframes on the currently active property";
+
+ /* callbacks */
+ ot->exec = clear_key_button_exec;
+ ot->poll = modify_key_op_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Clear keyframes from all elements of the array");
+}
+
/* ******************************************* */
/* AUTO KEYFRAME */
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 3099fcb2b40..5d62ef768d2 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -212,6 +212,12 @@ void ui_but_anim_delete_keyframe(bContext *C)
WM_operator_name_call(C, "ANIM_OT_keyframe_delete_button", WM_OP_INVOKE_DEFAULT, NULL);
}
+void ui_but_anim_clear_keyframe(bContext *C)
+{
+ /* this operator calls uiContextActiveProperty */
+ WM_operator_name_call(C, "ANIM_OT_keyframe_clear_button", WM_OP_INVOKE_DEFAULT, NULL);
+}
+
void ui_but_anim_add_driver(bContext *C)
{
/* this operator calls uiContextActiveProperty */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 0a9665ffc15..91b3b3ea622 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -4474,6 +4474,19 @@ static int ui_but_menu(bContext *C, uiBut *but)
ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
}
+ if (but->flag & UI_BUT_ANIMATED) {
+ if (length) {
+ uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
+ ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1);
+ uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"),
+ ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
+ }
+ else {
+ uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
+ ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
+ }
+ }
+
/* Drivers */
if (but->flag & UI_BUT_DRIVEN) {
uiItemS(layout);
@@ -4687,11 +4700,18 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
ui_but_drop(C, event, but, data);
}
/* handle keyframing */
- else if (event->type == IKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
- if (event->alt)
- ui_but_anim_delete_keyframe(C);
- else
+ else if (event->type == IKEY && !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) && event->val == KM_PRESS) {
+ if (event->alt) {
+ if (event->shift) {
+ ui_but_anim_clear_keyframe(C);
+ }
+ else {
+ ui_but_anim_delete_keyframe(C);
+ }
+ }
+ else {
ui_but_anim_insert_keyframe(C);
+ }
ED_region_tag_redraw(CTX_wm_region(C));
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 1f88db033a4..c6787b4c554 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -508,6 +508,7 @@ void ui_but_add_shortcut(uiBut *but, const char *key_str, const short do_strip);
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_clear_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_copy_driver(struct bContext *C);