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:
authorJoshua Leung <aligorith@gmail.com>2008-12-27 14:44:00 +0300
committerJoshua Leung <aligorith@gmail.com>2008-12-27 14:44:00 +0300
commit86886cbc55c036af44833fd861cfd276fbec256a (patch)
treea78d4c9ad57668c7dd15539858963a5bed0af65f
parent032adf70d9a839d99e1b80a97adc710a2b2d1b7d (diff)
2.5 - Action Editor
* Started porting back keyframe editing tools for the Action Editor/Dopesheet. Currently, only Snap (Shift-S) and Mirror (Shift-M) are functional. * Added keyframe-editing API method for ensuring that all IPO-curves are left in a valid state after modifiying the values of their keyframes. * Added operator-register flags for most of the operators. Only mouse-select doesn't have it for now (as there's not much useful info stored, and no exec callback).
-rw-r--r--source/blender/editors/animation/keyframes_edit.c215
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h32
-rw-r--r--source/blender/editors/screen/screen_ops.c6
-rw-r--r--source/blender/editors/space_action/action_edit_keyframes.c352
-rw-r--r--source/blender/editors/space_action/action_intern.h27
-rw-r--r--source/blender/editors/space_action/action_ops.c11
-rw-r--r--source/blender/editors/space_action/action_select.c32
7 files changed, 475 insertions, 200 deletions
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index a3a04901533..e58516bf1b8 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -145,6 +145,34 @@ short animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, BeztEd
}
/* ************************************************************************** */
+/* Keyframe Integrity Tools */
+
+/* Rearrange keyframes if some are out of order */
+// used to be recalc_*_ipos() where * was object or action
+void ANIM_editkeyframes_refresh(bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* filter animation data */
+ filter= ANIMFILTER_ONLYICU;
+ ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+
+ /* loop over ipo-curves that are likely to have been edited, and check them */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ IpoCurve *icu= ale->key_data;
+
+ /* make sure keyframes in IPO-curve are all in order, and handles are in valid positions */
+ sort_time_ipocurve(icu);
+ testhandles_ipocurve(icu);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+}
+
+/* ************************************************************************** */
/* BezTriple Validation Callbacks */
static short ok_bezier_frame(BeztEditData *bed, BezTriple *bezt)
@@ -286,44 +314,10 @@ static short mirror_bezier_xaxis(BeztEditData *bed, BezTriple *bezt)
static short mirror_bezier_marker(BeztEditData *bed, BezTriple *bezt)
{
- static TimeMarker *marker;
- static short initialised = 0;
- const Scene *scene= bed->scene;
-
- /* In order for this mirror function to work without
- * any extra arguments being added, we use the case
- * of bezt==NULL to denote that we should find the
- * marker to mirror over. The static pointer is safe
- * to use this way, as it will be set to null after
- * each cycle in which this is called.
- */
-
- if (bezt) {
- /* mirroring time */
- if ((bezt->f2 & SELECT) && (marker)) {
- const float diff= (marker->frame - bezt->vec[1][0]);
- bezt->vec[1][0]= (marker->frame + diff);
- }
- }
- else {
- /* initialisation time */
- if (initialised) {
- /* reset everything for safety */
- marker = NULL;
- initialised = 0;
- }
- else {
- /* try to find a marker */
- for (marker= scene->markers.first; marker; marker=marker->next) {
- if (marker->flag & SELECT) {
- initialised = 1;
- break;
- }
- }
-
- if (initialised == 0)
- marker = NULL;
- }
+ /* mirroring time stored in f1 */
+ if (bezt->f2 & SELECT) {
+ const float diff= (bed->f1 - bezt->vec[1][0]);
+ bezt->vec[1][0]= (bed->f1 + diff);
}
return 0;
@@ -334,20 +328,22 @@ static short mirror_bezier_marker(BeztEditData *bed, BezTriple *bezt)
BeztEditFunc ANIM_editkeyframes_mirror(short type)
{
switch (type) {
- case 1: /* mirror over current frame */
+ case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
return mirror_bezier_cframe;
- case 2: /* mirror over frame 0 */
+ case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
return mirror_bezier_yaxis;
- case 3: /* mirror over value 0 */
+ case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
return mirror_bezier_xaxis;
- case 4: /* mirror over marker */
- return mirror_bezier_marker; // XXX in past, this func was called before/after with NULL, probably will need globals instead
+ case MIRROR_KEYS_MARKER: /* mirror over marker */
+ return mirror_bezier_marker;
default: /* just in case */
return mirror_bezier_yaxis;
break;
}
}
+/* --------- */
+
/* This function is called to calculate the average location of the
* selected keyframes, and place the current frame at that location.
*
@@ -654,6 +650,7 @@ short is_ipo_key_selected(Ipo *ipo)
return 0;
}
+// XXX although this is still needed, it should be removed!
void set_ipo_key_selection(Ipo *ipo, short sel)
{
IpoCurve *icu;
@@ -678,6 +675,7 @@ void set_ipo_key_selection(Ipo *ipo, short sel)
}
}
+// XXX port this over to the new system!
// err... this is this still used?
int fullselect_ipo_keys(Ipo *ipo)
{
@@ -701,134 +699,3 @@ int fullselect_ipo_keys(Ipo *ipo)
return tvtot;
}
-
-void borderselect_icu_key(IpoCurve *icu, float xmin, float xmax, BeztEditFunc select_cb)
-{
- /* Selects all bezier triples in the Ipocurve
- * between times xmin and xmax, using the selection
- * function.
- */
- BezTriple *bezt;
- int i;
-
- /* loop through all of the bezier triples in
- * the Ipocurve -- if the triple occurs between
- * times xmin and xmax then select it using the selection
- * function
- */
- for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
- if ((bezt->vec[1][0] > xmin) && (bezt->vec[1][0] < xmax)) {
- /* scene is NULL (irrelevant here) */
- select_cb(NULL, bezt);
- }
- }
-}
-
-void borderselect_ipo_key(Ipo *ipo, float xmin, float xmax, short selectmode)
-{
- /* Selects all bezier triples in each Ipocurve of the
- * Ipo between times xmin and xmax, using the selection mode.
- */
-
- IpoCurve *icu;
- BeztEditFunc select_cb;
-
- /* If the ipo is no good then return */
- if (ipo == NULL)
- return;
-
- /* Set the selection function based on the
- * selection mode.
- */
- select_cb= ANIM_editkeyframes_select(selectmode);
- if (select_cb == NULL)
- return;
-
- /* loop through all of the bezier triples in all
- * of the Ipocurves -- if the triple occurs between
- * times xmin and xmax then select it using the selection
- * function
- */
- for (icu=ipo->curve.first; icu; icu=icu->next) {
- borderselect_icu_key(icu, xmin, xmax, select_cb);
- }
-}
-
-void select_icu_key(BeztEditData *bed, IpoCurve *icu, float selx, short selectmode)
-{
- /* Selects all bezier triples in the Ipocurve
- * at time selx, using the selection mode.
- * This is kind of sloppy the obvious similarities
- * with the above function, forgive me ...
- */
- BeztEditFunc select_cb;
- BezTriple *bezt;
- int i;
-
- /* If the icu is no good then return */
- if (icu == NULL)
- return;
-
- /* Set the selection function based on the selection mode. */
- switch (selectmode) {
- case SELECT_ADD:
- select_cb = select_bezier_add;
- break;
- case SELECT_SUBTRACT:
- select_cb = select_bezier_subtract;
- break;
- case SELECT_INVERT:
- select_cb = select_bezier_invert;
- break;
- default:
- return;
- }
-
- /* loop through all of the bezier triples in
- * the Ipocurve -- if the triple occurs at
- * time selx then select it using the selection
- * function
- */
- for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
- if (bezt->vec[1][0] == selx) {
- select_cb(bed, bezt);
- }
- }
-}
-
-void select_ipo_key(BeztEditData *bed, Ipo *ipo, float selx, short selectmode)
-{
- /* Selects all bezier triples in each Ipocurve of the
- * Ipo at time selx, using the selection mode.
- */
- IpoCurve *icu;
- BezTriple *bezt;
- BeztEditFunc select_cb;
- int i;
-
- /* If the ipo is no good then return */
- if (ipo == NULL)
- return;
-
- /* Set the selection function based on the
- * selection mode.
- */
- select_cb= ANIM_editkeyframes_select(selectmode);
- if (select_cb == NULL)
- return;
-
- /* loop through all of the bezier triples in all
- * of the Ipocurves -- if the triple occurs at
- * time selx then select it using the selection
- * function
- */
- for (icu=ipo->curve.first; icu; icu=icu->next) {
- for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
- if (bezt->vec[1][0] == selx) {
- select_cb(bed, bezt);
- }
- }
- }
-}
-
-
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index 56a4cb6089c..36ec834635e 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -29,6 +29,7 @@
#ifndef ED_KEYFRAMES_EDIT_H
#define ED_KEYFRAMES_EDIT_H
+struct bAnimContext;
struct Ipo;
struct IpoCurve;
struct BezTriple;
@@ -67,16 +68,19 @@ typedef enum eEditKeyframes_Select {
/* snapping tools */
typedef enum eEditKeyframes_Snap {
- SNAP_KEYS_NEARFRAME = 1,
- SNAP_KEYS_CURFRAME,
- SNAP_KEYS_NEARMARKER,
+ SNAP_KEYS_CURFRAME = 1,
+ SNAP_KEYS_NEARFRAME,
SNAP_KEYS_NEARSEC,
+ SNAP_KEYS_NEARMARKER,
} eEditKeyframes_Snap;
/* mirroring tools */
-//typedef enum eEditKeyframes_Mirror {
-
-//} eEditKeyframes_Mirror;
+typedef enum eEditKeyframes_Mirror {
+ MIRROR_KEYS_CURFRAME = 1,
+ MIRROR_KEYS_YAXIS,
+ MIRROR_KEYS_XAXIS,
+ MIRROR_KEYS_MARKER,
+} eEditKeyframes_Mirror;
/* ************************************************ */
/* Editing API */
@@ -92,19 +96,23 @@ typedef struct BeztEditData {
int i1, i2; /* storage of times/values as 'whole' numbers */
} BeztEditData;
-/* ------- Function Pointer Typedefs --------------- */
+/* ------- Function Pointer Typedefs ---------------- */
/* callback function that refreshes the IPO curve after use */
typedef void (*IcuEditFunc)(struct IpoCurve *icu);
/* callback function that operates on the given BezTriple */
typedef short (*BeztEditFunc)(BeztEditData *bed, struct BezTriple *bezt);
-/* ------------- Looping API ------------------- */
+/* ---------------- Looping API --------------------- */
+/* functions for looping over keyframes */
short icu_keys_bezier_loop(BeztEditData *bed, struct IpoCurve *icu, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, IcuEditFunc icu_cb);
short ipo_keys_bezier_loop(BeztEditData *bed, struct Ipo *ipo, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, IcuEditFunc icu_cb);
-/* ------------ BezTriple Callback Getters --------------- */
+/* functions for making sure all keyframes are in good order */
+void ANIM_editkeyframes_refresh(struct bAnimContext *ac);
+
+/* ----------- BezTriple Callback Getters ---------- */
/* accessories */
BeztEditFunc ANIM_editkeyframes_ok(short mode);
@@ -120,15 +128,9 @@ BeztEditFunc ANIM_editkeyframes_ipo(short mode);
// XXX all of these funcs will be depreceated!
-void select_ipo_key(BeztEditData *bed, struct Ipo *ipo, float selx, short selectmode);
-void select_icu_key(BeztEditData *bed, struct IpoCurve *icu, float selx, short selectmode);
-
short is_ipo_key_selected(struct Ipo *ipo);
void set_ipo_key_selection(struct Ipo *ipo, short sel);
-void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, short selectmode);
-void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax, BeztEditFunc select_cb);
-
/* ************************************************ */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 6dfb99397f7..5f38081f7fc 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -1525,9 +1525,9 @@ void ED_keymap_screen(wmWindowManager *wm)
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL, 0);
/* tests */
- RNA_enum_set(WM_keymap_add_item(keymap, "SCREEN_OT_region_split", SKEY, KM_PRESS, 0, 0)->ptr, "dir", 'h');
- RNA_enum_set(WM_keymap_add_item(keymap, "SCREEN_OT_region_split", SKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "dir", 'v');
-
+ RNA_enum_set(WM_keymap_add_item(keymap, "SCREEN_OT_region_split", SKEY, KM_PRESS, KM_CTRL|KM_ALT, 0)->ptr, "dir", 'h');
+ RNA_enum_set(WM_keymap_add_item(keymap, "SCREEN_OT_region_split", SKEY, KM_PRESS, KM_CTRL|KM_ALT|KM_SHIFT, 0)->ptr, "dir", 'v');
+
/*frame offsets*/
WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", TIMER0, KM_ANY, KM_ANY, 0);
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10);
diff --git a/source/blender/editors/space_action/action_edit_keyframes.c b/source/blender/editors/space_action/action_edit_keyframes.c
new file mode 100644
index 00000000000..8423aebfafe
--- /dev/null
+++ b/source/blender/editors/space_action/action_edit_keyframes.c
@@ -0,0 +1,352 @@
+/**
+ * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_listBase.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "BKE_action.h"
+#include "BKE_depsgraph.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+
+#include "UI_view2d.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_draw.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "action_intern.h"
+
+/* ************************************************************************** */
+/* GENERAL STUFF */
+
+/* ************************************************************************** */
+/* SETTINGS STUFF */
+
+/* ************************************************************************** */
+/* TRANSFORM STUFF */
+
+/* ***************** Snap Current Frame Operator *********************** */
+
+/* snap current-frame indicator to 'average time' of selected keyframe */
+static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+
+ //ListBase anim_data= {NULL, NULL};
+ //bAnimListElem *ale;
+ //int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ // FIXME... to be coded
+
+ /* 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_cfrasnap (wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Current Frame Snap to Keys";
+ ot->idname= "ACT_OT_keyframes_cfrasnap";
+
+ /* api callbacks */
+ ot->exec= actkeys_cfrasnap_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+}
+
+/* ******************** Snap Keyframes Operator *********************** */
+
+/* defines for snap keyframes tool */
+EnumPropertyItem prop_actkeys_snap_types[] = {
+ {ACTKEYS_SNAP_CFRA, "CFRA", "Current frame", ""},
+ {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", "Nearest Frame", ""}, // XXX as single entry?
+ {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", "Nearest Second", ""}, // XXX as single entry?
+ {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", "Nearest Marker", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for snapping keyframes to frame-times */
+static void snap_action_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc edit_cb;
+
+ /* 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);
+
+ /* get beztriple editing callbacks */
+ edit_cb= ANIM_editkeyframes_snap(mode);
+
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.scene= ac->scene;
+
+ /* snap keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply(nob, ale->key_data, 0, 1);
+ ipo_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_ipocurve);
+ ANIM_nla_mapping_apply(nob, ale->key_data, 1, 1);
+ }
+ //else if (ale->type == ACTTYPE_GPLAYER)
+ // snap_gplayer_frames(ale->data, mode);
+ else
+ ipo_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_ipocurve);
+ }
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_snap_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get snapping mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* snap keyframes */
+ snap_action_keys(&ac, mode);
+
+ /* 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_snap (wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Snap Keys";
+ ot->idname= "ACT_OT_keyframes_snap";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= actkeys_snap_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
+ /* id-props */
+ prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_actkeys_snap_types);
+}
+
+/* ******************** Mirror Keyframes Operator *********************** */
+
+/* defines for snap keyframes tool */
+EnumPropertyItem prop_actkeys_mirror_types[] = {
+ {ACTKEYS_MIRROR_CFRA, "CFRA", "Current frame", ""},
+ {ACTKEYS_MIRROR_YAXIS, "YAXIS", "Vertical Axis", ""},
+ {ACTKEYS_MIRROR_XAXIS, "XAXIS", "Horizontal Axis", ""},
+ {ACTKEYS_MIRROR_MARKER, "MARKER", "First Selected Marker", ""},
+ {0, NULL, NULL, NULL}
+};
+
+/* this function is responsible for snapping keyframes to frame-times */
+static void mirror_action_keys(bAnimContext *ac, short mode)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ BeztEditData bed;
+ BeztEditFunc edit_cb;
+
+ /* get beztriple editing callbacks */
+ edit_cb= ANIM_editkeyframes_mirror(mode);
+
+ memset(&bed, 0, sizeof(BeztEditData));
+ bed.scene= ac->scene;
+
+ /* for 'first selected marker' mode, need to find first selected marker first! */
+ // XXX should this be made into a helper func in the API?
+ if (mode == ACTKEYS_MIRROR_MARKER) {
+ Scene *scene= ac->scene;
+ TimeMarker *marker= NULL;
+
+ /* find first selected marker */
+ for (marker= scene->markers.first; marker; marker=marker->next) {
+ if (marker->flag & SELECT) {
+ break;
+ }
+ }
+
+ /* store marker's time (if available) */
+ if (marker)
+ bed.f1= marker->frame;
+ else
+ return;
+ }
+
+ /* 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);
+
+ /* mirror keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ Object *nob= ANIM_nla_mapping_get(ac, ale);
+
+ if (nob) {
+ ANIM_nla_mapping_apply(nob, ale->key_data, 0, 1);
+ ipo_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_ipocurve);
+ ANIM_nla_mapping_apply(nob, ale->key_data, 1, 1);
+ }
+ //else if (ale->type == ACTTYPE_GPLAYER)
+ // snap_gplayer_frames(ale->data, mode);
+ else
+ ipo_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_ipocurve);
+ }
+ BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_mirror_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ short mode;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get snapping mode */
+ mode= RNA_enum_get(op->ptr, "type");
+
+ /* mirror keyframes */
+ mirror_action_keys(&ac, mode);
+
+ /* 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_mirror (wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name= "Mirror Keys";
+ ot->idname= "ACT_OT_keyframes_mirror";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= actkeys_mirror_exec;
+ ot->poll= ED_operator_areaactive;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
+ /* id-props */
+ prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_actkeys_mirror_types);
+}
+
+/* ************************************************************************** */
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index 27d8ada37ac..7719bf4ba34 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -48,6 +48,7 @@ void action_header_buttons(const struct bContext *C, struct ARegion *ar);
/* ***************************************** */
/* action_select.c */
+
void ACT_OT_keyframes_deselectall(struct wmOperatorType *ot);
void ACT_OT_keyframes_borderselect(struct wmOperatorType *ot);
void ACT_OT_keyframes_columnselect(struct wmOperatorType *ot);
@@ -70,6 +71,32 @@ enum {
} eActKeys_ColumnSelect_Mode;
/* ***************************************** */
+/* action_edit_keyframes.c */
+
+void ACT_OT_keyframes_snap(struct wmOperatorType *ot);
+void ACT_OT_keyframes_mirror(struct wmOperatorType *ot);
+
+/* defines for snap keyframes
+ * NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
+ */
+enum {
+ ACTKEYS_SNAP_CFRA = 1,
+ ACTKEYS_SNAP_NEAREST_FRAME,
+ ACTKEYS_SNAP_NEAREST_SECOND,
+ ACTKEYS_SNAP_NEAREST_MARKER,
+} eActKeys_Snap_Mode;
+
+/* defines for mirror keyframes
+ * NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
+ */
+enum {
+ ACTKEYS_MIRROR_CFRA = 1,
+ ACTKEYS_MIRROR_YAXIS,
+ ACTKEYS_MIRROR_XAXIS,
+ ACTKEYS_MIRROR_MARKER,
+} eActKeys_Mirror_Mode;
+
+/* ***************************************** */
/* action_ops.c */
void action_operatortypes(void);
void action_keymap(struct wmWindowManager *wm);
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index 19850917a9c..51b8800c1ea 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -62,10 +62,15 @@ void action_operatortypes(void)
/* channels */
/* keyframes */
+ /* selection */
WM_operatortype_append(ACT_OT_keyframes_clickselect);
WM_operatortype_append(ACT_OT_keyframes_deselectall);
WM_operatortype_append(ACT_OT_keyframes_borderselect);
WM_operatortype_append(ACT_OT_keyframes_columnselect);
+
+ /* editing */
+ WM_operatortype_append(ACT_OT_keyframes_snap);
+ WM_operatortype_append(ACT_OT_keyframes_mirror);
}
/* ************************** registration - keymaps **********************************/
@@ -79,7 +84,6 @@ static void action_keymap_keyframes (ListBase *keymap)
RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend_select", 1);
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "left_right", ACTKEYS_LRSEL_TEST);
-
/* deselect all */
WM_keymap_add_item(keymap, "ACT_OT_keyframes_deselectall", AKEY, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_deselectall", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
@@ -93,6 +97,11 @@ static void action_keymap_keyframes (ListBase *keymap)
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA);
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN);
RNA_enum_set(WM_keymap_add_item(keymap, "ACT_OT_keyframes_columnselect", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN);
+
+ /* action_edit_keyframes.c */
+ /* menu+1-step transform */
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ACT_OT_keyframes_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
}
/* --------------- */
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index de41b7e4604..46bf2549087 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -411,6 +411,9 @@ void ACT_OT_keyframes_deselectall (wmOperatorType *ot)
ot->exec= actkeys_deselectall_exec;
ot->poll= ED_operator_areaactive;
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
/* props */
RNA_def_property(ot->srna, "invert", PROP_BOOLEAN, PROP_NONE);
}
@@ -577,6 +580,10 @@ void ACT_OT_keyframes_borderselect(wmOperatorType *ot)
ot->poll= ED_operator_areaactive;
+ /* flags */
+ // XXX er...
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
/* rna */
RNA_def_property(ot->srna, "event_type", PROP_INT, PROP_NONE);
RNA_def_property(ot->srna, "xmin", PROP_INT, PROP_NONE);
@@ -809,6 +816,9 @@ void ACT_OT_keyframes_columnselect (wmOperatorType *ot)
ot->exec= actkeys_columnselect_exec;
ot->poll= ED_operator_areaactive;
+ /* flags */
+ ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+
/* props */
prop= RNA_def_property(ot->srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_column_select_types);
@@ -1007,21 +1017,29 @@ static void selectkeys_leftright (bAnimContext *ac, short leftright, short selec
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+
+ BeztEditFunc ok_cb, select_cb;
+ BeztEditData bed;
Scene *scene= ac->scene;
- float min, max;
+ /* if select mode is replace, deselect all keyframes first */
if (select_mode==SELECT_REPLACE) {
select_mode=SELECT_ADD;
deselect_action_keys(ac, 0, 0);
}
+ /* set callbacks and editing data */
+ ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
+ select_cb= ANIM_editkeyframes_select(select_mode);
+
+ memset(&bed, 0, sizeof(BeztEditFunc));
if (leftright == ACTKEYS_LRSEL_LEFT) {
- min = -MAXFRAMEF;
- max = (float)(CFRA + 0.1f);
+ bed.f1 = -MAXFRAMEF;
+ bed.f2 = (float)(CFRA + 0.1f);
}
else {
- min = (float)(CFRA - 0.1f);
- max = MAXFRAMEF;
+ bed.f1 = (float)(CFRA - 0.1f);
+ bed.f2 = MAXFRAMEF;
}
/* filter data */
@@ -1037,13 +1055,13 @@ static void selectkeys_leftright (bAnimContext *ac, short leftright, short selec
if (nob) {
ANIM_nla_mapping_apply(nob, ale->key_data, 0, 1);
- borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
+ ipo_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
ANIM_nla_mapping_apply(nob, ale->key_data, 1, 1);
}
//else if (ale->type == ANIMTYPE_GPLAYER)
// borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
else
- borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
+ ipo_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
}
/* Cleanup */