/* GENERAL STUFF */
// TODO:
-// - clean
-// - sample
// - delete
// - insert key
// - copy/paste
+/* ******************** Delete Keyframes Operator ************************* */
+
+static void delete_action_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ if (ac->datatype == ANIMCONT_GPENCIL)
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
+ else
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
+ ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and delete selected keys */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ //if (ale->type == ANIMTYPE_GPLAYER)
+ // delete_gplayer_frames((bGPDlayer *)ale->data);
+ //else
+ delete_ipo_keys((Ipo *)ale->key_data);
+ }
+
+ /* free filtered list */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_delete_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* delete keyframes */
+ delete_action_keys(&ac);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier tha things have changed */
+ ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_delete (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Keyframes";
+ ot->idname= "ACT_OT_keyframes_delete";
+
+ /* api callbacks */
+ ot->exec= actkeys_delete_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+}
+
+/* ******************** Clean Keyframes Operator ************************* */
+
+static void clean_action_keys (bAnimContext *ac, float thresh)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_ONLYICU);
+ ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and clean curves */
+ for (ale= anim_data.first; ale; ale= ale->next)
+ clean_ipo_curve((IpoCurve *)ale->key_data, thresh);
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_clean_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ float thresh;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* get cleaning threshold */
+ thresh= RNA_float_get(op->ptr, "threshold");
+
+ /* clean keyframes */
+ clean_action_keys(&ac, thresh);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier tha things have changed */
+ ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_clean (wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Clean Keyframes";
+ ot->idname= "ACT_OT_keyframes_clean";
+
+ /* api callbacks */
+ //ot->invoke= // XXX we need that number popup for this!
+ ot->exec= actkeys_clean_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
+ /* properties */
+ prop= RNA_def_property(ot->srna, "threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_default(prop, 0.001f);
+}
+
+/* ******************** Sample Keyframes Operator *********************** */
+
+/* little cache for values... */
+typedef struct tempFrameValCache {
+ float frame, val;
+} tempFrameValCache;
+
+/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
+static void sample_action_keys (bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ONLYICU);
+ ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+
+ /* loop through filtered data and add keys between selected keyframes on every frame */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ IpoCurve *icu= (IpoCurve *)ale->key_data;
+ BezTriple *bezt, *start=NULL, *end=NULL;
+ tempFrameValCache *value_cache, *fp;
+ int sfra, range;
+ int i, n;
+
+ /* find selected keyframes... once pair has been found, add keyframes */
+ for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
+ /* check if selected, and which end this is */
+ if (BEZSELECTED(bezt)) {
+ if (start) {
+ /* set end */
+ end= bezt;
+
+ /* cache values then add keyframes using these values, as adding
+ * keyframes while sampling will affect the outcome...
+ */
+ range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) );
+ sfra= (int)( floor(start->vec[1][0]) );
+
+ if (range) {
+ value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache");
+
+ /* sample values */
+ for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
+ fp->frame= (float)(sfra + n);
+ fp->val= eval_icu(icu, fp->frame);
+ }
+
+ /* add keyframes with these */
+ for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
+ insert_vert_icu(icu, fp->frame, fp->val, 1);
+ }
+
+ /* free temp cache */
+ MEM_freeN(value_cache);
+
+ /* as we added keyframes, we need to compensate so that bezt is at the right place */
+ bezt = icu->bezt + i + range - 1;
+ i += (range - 1);
+ }
+
+ /* bezt was selected, so it now marks the start of a whole new chain to search */
+ start= bezt;
+ end= NULL;
+ }
+ else {
+ /* just set start keyframe */
+ start= bezt;
+ end= NULL;
+ }
+ }
+ }
+
+ /* recalculate channel's handles? */
+ calchandles_ipocurve(icu);
+ }
+
+ /* admin and redraws */
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_sample_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+ if (ac.datatype == ANIMCONT_GPENCIL)
+ return OPERATOR_PASS_THROUGH;
+
+ /* sample keyframes */
+ sample_action_keys(&ac);
+
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier tha things have changed */
+ ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+
+ return OPERATOR_FINISHED;
+}
+
+void ACT_OT_keyframes_sample (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Sample Keyframes";
+ ot->idname= "ACT_OT_keyframes_sample";
+
+ /* api callbacks */
+ ot->exec= actkeys_sample_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+}
+
/* ************************************************************************** */
/* SETTINGS STUFF */
-// TODO:
-// - wkey stuff
-
/* ******************** Set Extrapolation-Type Operator *********************** */
/* defines for set ipo-type for selected keyframes tool */