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:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2012-07-21 03:12:05 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2012-07-21 03:12:05 +0400
commit3b012c041f1fb7b78eddcf1f93288cf7a86ab8d6 (patch)
treecead235bff7687610b1372e709e742ef70692dcb /source/blender/editors/animation
parent5a581c1fd116c51df13e09c5c320feba48d069bb (diff)
parent16516238e2b25ce53144c2dcea5323dc7313b724 (diff)
Merged changes in the trunk up to revision 49090.
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c54
-rw-r--r--source/blender/editors/animation/anim_filter.c53
-rw-r--r--source/blender/editors/animation/anim_intern.h1
-rw-r--r--source/blender/editors/animation/anim_markers.c8
-rw-r--r--source/blender/editors/animation/anim_ops.c1
-rw-r--r--source/blender/editors/animation/keyframes_draw.c21
-rw-r--r--source/blender/editors/animation/keyframing.c157
7 files changed, 227 insertions, 68 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 6331dd51527..e890b8f2aba 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -852,7 +852,7 @@ static int acf_group_setting_flag(bAnimContext *ac, int setting, short *neg)
// *neg = 1; - if we change this to edtiability
return AGRP_PROTECTED;
- case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */
+ case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
*neg = 1;
return AGRP_NOTVISIBLE;
}
@@ -940,7 +940,7 @@ static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), int setting, short
// *neg = 1; - if we change this to edtiability
return FCURVE_PROTECTED;
- case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */
+ case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
return FCURVE_VISIBLE;
default: /* unsupported */
@@ -2585,11 +2585,11 @@ static bAnimChannelType ACF_GPL =
acf_generic_channel_backdrop, /* backdrop */
acf_generic_indention_flexible, /* indent level */
acf_generic_group_offset, /* offset */
-
+
acf_gpl_name, /* name */
acf_gpl_name_prop, /* name prop */
NULL, /* icon */
-
+
acf_gpl_setting_valid, /* has setting */
acf_gpl_setting_flag, /* flag for setting */
acf_gpl_setting_ptr /* pointer for setting */
@@ -2619,7 +2619,7 @@ static short acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNU
case ACHANNEL_SETTING_SELECT:
case ACHANNEL_SETTING_EXPAND:
return 1;
-
+
default:
return 0;
}
@@ -2630,15 +2630,15 @@ static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), int setting, short *n
{
/* clear extra return data first */
*neg = 0;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return AGRP_SELECTED;
-
+
case ACHANNEL_SETTING_EXPAND: /* expanded */
return MASK_ANIMF_EXPAND;
}
-
+
/* this shouldn't happen */
return 0;
}
@@ -2647,7 +2647,7 @@ static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), int setting, short *n
static void *acf_mask_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type)
{
Mask *mask = (Mask *)ale->data;
-
+
/* all flags are just in mask->flag for now... */
return GET_ACF_FLAG_PTR(mask->flag, type);
}
@@ -2656,16 +2656,16 @@ static void *acf_mask_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short
static bAnimChannelType ACF_MASKDATA =
{
"Mask Datablock", /* type name */
-
+
acf_mask_color, /* backdrop color */
acf_group_backdrop, /* backdrop */
acf_generic_indention_0, /* indent level */
acf_generic_group_offset, /* offset */
-
+
acf_generic_idblock_name, /* name */
acf_generic_idfill_nameprop, /* name prop */
acf_mask_icon, /* icon */
-
+
acf_mask_setting_valid, /* has setting */
acf_mask_setting_flag, /* flag for setting */
acf_mask_setting_ptr /* pointer for setting */
@@ -2677,7 +2677,7 @@ static bAnimChannelType ACF_MASKDATA =
static void acf_masklay_name(bAnimListElem *ale, char *name)
{
MaskLayer *masklay = (MaskLayer *)ale->data;
-
+
if (masklay && name)
BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
}
@@ -2688,7 +2688,7 @@ static short acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, Property
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
-
+
return (*prop != NULL);
}
@@ -2703,7 +2703,7 @@ static short acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *
case ACHANNEL_SETTING_EXPAND: /* mask layers are more like F-Curves than groups */
case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
return 0;
-
+
/* always available */
default:
return 1;
@@ -2715,18 +2715,18 @@ static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short
{
/* clear extra return data first */
*neg = 0;
-
+
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return MASK_LAYERFLAG_SELECT;
-
+
// case ACHANNEL_SETTING_MUTE: /* muted */
// return GP_LAYER_HIDE;
-
+
case ACHANNEL_SETTING_PROTECT: /* protected */
// *neg = 1; - if we change this to edtiability
return MASK_LAYERFLAG_LOCKED;
-
+
default: /* unsupported */
return 0;
}
@@ -2780,17 +2780,17 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = NULL; /* None */
animchannelTypeInfo[type++] = NULL; /* AnimData */
animchannelTypeInfo[type++] = NULL; /* Special */
-
+
animchannelTypeInfo[type++] = &ACF_SUMMARY; /* Motion Summary */
-
+
animchannelTypeInfo[type++] = &ACF_SCENE; /* Scene */
animchannelTypeInfo[type++] = &ACF_OBJECT; /* Object */
animchannelTypeInfo[type++] = &ACF_GROUP; /* Group */
animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */
-
+
animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */
animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */
-
+
animchannelTypeInfo[type++] = &ACF_DSMAT; /* Material Channel */
animchannelTypeInfo[type++] = &ACF_DSLAM; /* Lamp Channel */
animchannelTypeInfo[type++] = &ACF_DSCAM; /* Camera Channel */
@@ -2806,15 +2806,15 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
-
+
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
-
+
animchannelTypeInfo[type++] = &ACF_GPD; /* Grease Pencil Datablock */
animchannelTypeInfo[type++] = &ACF_GPL; /* Grease Pencil Layer */
-
+
animchannelTypeInfo[type++] = &ACF_MASKDATA; /* Mask Datablock */
animchannelTypeInfo[type++] = &ACF_MASKLAYER; /* Mask Layer */
-
+
// TODO: these types still need to be implemented!!!
// probably need a few extra flags for these special cases...
animchannelTypeInfo[type++] = NULL; /* NLA Track */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 81b6d77dd82..035641b2888 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -418,16 +418,16 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
*
* For this to work correctly, a standard set of data needs to be available within the scope that this
* gets called in:
- * - ListBase anim_data;
- * - bDopeSheet *ads;
- * - bAnimListElem *ale;
+ * - ListBase anim_data;
+ * - bDopeSheet *ads;
+ * - bAnimListElem *ale;
* - size_t items;
*
* - id: ID block which should have an AnimData pointer following it immediately, to use
- * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
- * - nlaOk: line or block of code to execute for NLA tracks+strips case
- * - driversOk: line or block of code to execute for Drivers case
- * - keysOk: line or block of code for Keyframes case
+ * - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
+ * - nlaOk: line or block of code to execute for NLA tracks+strips case
+ * - driversOk: line or block of code to execute for Drivers case
+ * - keysOk: line or block of code for Keyframes case
*
* The checks for the various cases are as follows:
* 0) top level: checks for animdata and also that all the F-Curves for the block will be visible
@@ -1330,6 +1330,7 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke
return items;
}
+/* Helper for Grease Pencil - layers within a datablock */
static size_t animdata_filter_gpencil_data(ListBase *anim_data, bGPdata *gpd, int filter_mode)
{
bGPDlayer *gpl;
@@ -1396,6 +1397,7 @@ static size_t animdata_filter_gpencil(ListBase *anim_data, void *UNUSED(data), i
return items;
}
+/* Helper for Mask Editing - mask layers */
static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
{
MaskLayer *masklay_act = BKE_mask_layer_active(mask);
@@ -1412,18 +1414,6 @@ static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const i
if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) {
/* add to list */
ANIMCHANNEL_NEW_CHANNEL(masklay, ANIMTYPE_MASKLAYER, mask);
-
-
-// if (filter_mode & ANIMFILTER_TMP_PEEK)
-// return 1;
-// else {
-// bAnimListElem *ale = make_new_animlistelem(masklay, channel_type, (ID *)owner_id);
-// if (ale) {
-// BLI_addtail(anim_data, ale);
-// items ++;
-// }
-// }
-
}
// }
}
@@ -1432,28 +1422,29 @@ static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const i
return items;
}
+/* Grab all mask data */
static size_t animdata_filter_mask(ListBase *anim_data, void *UNUSED(data), int filter_mode)
{
Mask *mask;
size_t items = 0;
-
- /* for now, grab grease pencil datablocks directly from main */
+
+ /* for now, grab mask datablocks directly from main */
// XXX: this is not good...
for (mask = G.main->mask.first; mask; mask = mask->id.next) {
ListBase tmp_data = {NULL, NULL};
size_t tmp_items = 0;
-
- /* only show if gpd is used by something... */
+
+ /* only show if mask is used by something... */
if (ID_REAL_USERS(mask) < 1)
continue;
-
- /* add gpencil animation channels */
+
+ /* add mask animation channels */
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MASK(mask))
{
tmp_items += animdata_filter_mask_data(&tmp_data, mask, filter_mode);
}
END_ANIMFILTER_SUBCHANNELS;
-
+
/* did we find anything? */
if (tmp_items) {
/* include data-expand widget first */
@@ -1461,14 +1452,14 @@ static size_t animdata_filter_mask(ListBase *anim_data, void *UNUSED(data), int
/* add gpd as channel too (if for drawing, and it has layers) */
ANIMCHANNEL_NEW_CHANNEL(mask, ANIMTYPE_MASKDATABLOCK, NULL);
}
-
+
/* now add the list of collected channels */
BLI_movelisttolist(anim_data, &tmp_data);
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
items += tmp_items;
}
}
-
+
/* return the number of items added to the list */
return items;
}
@@ -2453,7 +2444,7 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo
items += animfilter_action(ac, anim_data, ads, data, filter_mode, (ID *)obact);
}
break;
-
+
case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
{
/* the check for the DopeSheet summary is included here since the summary works here too */
@@ -2468,14 +2459,14 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo
items = animdata_filter_gpencil(anim_data, data, filter_mode);
}
break;
-
+
case ANIMCONT_MASK:
{
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
items = animdata_filter_mask(anim_data, data, filter_mode);
}
break;
-
+
case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
{
/* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
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_markers.c b/source/blender/editors/animation/anim_markers.c
index ea344e7e332..96044e2408e 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -848,14 +848,14 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
}
if (evt->val == KM_PRESS) {
- float vec[3];
- char str_tx[256];
+ float vec;
+ char str_tx[NUM_STR_REP_LEN];
if (handleNumInput(&mm->num, evt)) {
- applyNumInput(&mm->num, vec);
+ applyNumInput(&mm->num, &vec);
outputNumInput(&mm->num, str_tx);
- RNA_int_set(op->ptr, "frames", vec[0]);
+ RNA_int_set(op->ptr, "frames", vec);
ed_marker_move_apply(op);
// ed_marker_header_update(C, op, str, (int)vec[0]);
// strcat(str, str_tx);
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/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 84711b97729..85731933168 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -674,15 +674,15 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
if (keys) {
/* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
/* TODO: allow this opacity factor to be themed? */
- float kalpha = (channelLocked) ? 0.35f : 1.0f;
-
+ float kalpha = (channelLocked) ? 0.25f : 1.0f;
+
for (ak = keys->first; ak; ak = ak->next) {
/* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
* - this might give some improvements, since we current have to flip between view/region matrices
*/
if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
continue;
-
+
/* draw using OpenGL - uglier but faster */
/* NOTE1: a previous version of this didn't work nice for some intel cards
* NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */
@@ -753,6 +753,10 @@ void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
{
DLRBT_Tree keys, blocks;
+ short locked = (fcu->flag & FCURVE_PROTECTED) ||
+ ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
+ ((adt && adt->action) && (adt->action->id.lib));
+
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
@@ -761,7 +765,7 @@ void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, (fcu->flag & FCURVE_PROTECTED));
+ draw_keylist(v2d, &keys, &blocks, ypos, locked);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
@@ -771,6 +775,9 @@ void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float y
{
DLRBT_Tree keys, blocks;
+ short locked = (agrp->flag & AGRP_PROTECTED) ||
+ ((adt && adt->action) && (adt->action->id.lib));
+
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
@@ -779,7 +786,7 @@ void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float y
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, (agrp->flag & AGRP_PROTECTED));
+ draw_keylist(v2d, &keys, &blocks, ypos, locked);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
@@ -789,6 +796,8 @@ void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
{
DLRBT_Tree keys, blocks;
+ short locked = (act->id.lib != 0);
+
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
@@ -797,7 +806,7 @@ void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, 0);
+ draw_keylist(v2d, &keys, &blocks, ypos, locked);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
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 */