diff options
author | Joshua Leung <aligorith@gmail.com> | 2008-12-27 14:44:00 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2008-12-27 14:44:00 +0300 |
commit | 86886cbc55c036af44833fd861cfd276fbec256a (patch) | |
tree | a78d4c9ad57668c7dd15539858963a5bed0af65f /source | |
parent | 032adf70d9a839d99e1b80a97adc710a2b2d1b7d (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).
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/animation/keyframes_edit.c | 215 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframes_edit.h | 32 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_edit_keyframes.c | 352 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_intern.h | 27 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_ops.c | 11 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_select.c | 32 |
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 */ |