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).
This commit is contained in:
@@ -144,6 +144,34 @@ short animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, BeztEd
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* 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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
/* ************************************************ */
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
352
source/blender/editors/space_action/action_edit_keyframes.c
Normal file
352
source/blender/editors/space_action/action_edit_keyframes.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
@@ -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);
|
||||
@@ -69,6 +70,32 @@ enum {
|
||||
ACTKEYS_COLUMNSEL_MARKERS_BETWEEN,
|
||||
} 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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
||||
@@ -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;
|
||||
Scene *scene= ac->scene;
|
||||
float min, max;
|
||||
|
||||
BeztEditFunc ok_cb, select_cb;
|
||||
BeztEditData bed;
|
||||
Scene *scene= ac->scene;
|
||||
|
||||
/* 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 */
|
||||
|
||||
Reference in New Issue
Block a user