2011-02-23 10:52:22 +00:00
/*
2009-06-23 00:09:26 +00:00
* $ Id $
2009-01-26 23:18:27 +00:00
*
* * * * * * 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 ,
2010-02-12 13:34:04 +00:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2009-01-26 23:18:27 +00:00
*
* 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 * * * * *
*/
2011-02-27 20:29:51 +00:00
/** \file blender/editors/space_graph/graph_edit.c
* \ ingroup spgraph
*/
2009-01-26 23:18:27 +00:00
# include <math.h>
# include <stdlib.h>
# include <string.h>
# include <float.h>
2010-01-01 05:09:30 +00:00
# include "AUD_C-API.h"
2009-01-26 23:18:27 +00:00
# include "MEM_guardedalloc.h"
# include "BLI_blenlib.h"
2009-11-10 20:43:45 +00:00
# include "BLI_math.h"
2011-01-07 18:36:47 +00:00
# include "BLI_utildefines.h"
2009-01-26 23:18:27 +00:00
# include "DNA_anim_types.h"
# include "DNA_object_types.h"
# include "DNA_scene_types.h"
# include "RNA_access.h"
# include "RNA_define.h"
2009-05-08 10:50:32 +00:00
# include "RNA_enum_types.h"
2009-01-26 23:18:27 +00:00
# include "BKE_fcurve.h"
2009-06-23 13:25:31 +00:00
# include "BKE_nla.h"
2009-01-26 23:18:27 +00:00
# include "BKE_context.h"
2009-02-24 11:23:04 +00:00
# include "BKE_report.h"
2009-01-26 23:18:27 +00:00
2009-07-03 01:10:46 +00:00
# include "UI_interface.h"
2011-02-27 18:03:19 +00:00
# include "UI_resources.h"
2009-01-26 23:18:27 +00:00
# include "UI_view2d.h"
# include "ED_anim_api.h"
# include "ED_keyframing.h"
# include "ED_keyframes_edit.h"
# include "ED_screen.h"
2009-07-08 16:17:47 +00:00
# include "ED_transform.h"
2011-01-06 04:35:57 +00:00
# include "ED_markers.h"
2009-01-26 23:18:27 +00:00
# include "WM_api.h"
# include "WM_types.h"
2009-02-03 12:04:05 +00:00
# include "graph_intern.h"
2009-01-26 23:18:27 +00:00
/* ************************************************************************** */
/* KEYFRAME-RANGE STUFF */
/* *************************** Calculate Range ************************** */
/* Get the min/max keyframes*/
2009-07-02 18:12:46 +00:00
/* note: it should return total boundbox, filter for selection only can be argument... */
2011-03-17 10:02:37 +00:00
void get_graph_keyframe_extents ( bAnimContext * ac , float * xmin , float * xmax , float * ymin , float * ymax , const short selOnly )
2009-01-26 23:18:27 +00:00
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
/* get data to filter, from Dopesheet */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* set large values to try to override */
if ( xmin ) * xmin = 999999999.0f ;
if ( xmax ) * xmax = - 999999999.0f ;
2009-02-10 10:42:04 +00:00
if ( ymin ) * ymin = 999999999.0f ;
if ( ymax ) * ymax = - 999999999.0f ;
2009-01-26 23:18:27 +00:00
/* check if any channels to set range with */
if ( anim_data . first ) {
/* go through channels, finding max extents */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
2009-06-23 13:25:31 +00:00
AnimData * adt = ANIM_nla_mapping_get ( ac , ale ) ;
2009-01-26 23:18:27 +00:00
FCurve * fcu = ( FCurve * ) ale - > key_data ;
2009-05-11 11:51:30 +00:00
float txmin , txmax , tymin , tymax ;
2010-01-26 03:16:14 +00:00
float unitFac ;
2009-01-26 23:18:27 +00:00
2010-01-26 03:16:14 +00:00
/* get range */
2011-03-17 10:02:37 +00:00
calc_fcurve_bounds ( fcu , & txmin , & txmax , & tymin , & tymax , selOnly ) ;
2009-01-26 23:18:27 +00:00
2010-01-26 03:16:14 +00:00
/* apply NLA scaling */
2009-06-23 13:25:31 +00:00
if ( adt ) {
2009-06-28 07:32:00 +00:00
txmin = BKE_nla_tweakedit_remap ( adt , txmin , NLATIME_CONVERT_MAP ) ;
txmax = BKE_nla_tweakedit_remap ( adt , txmax , NLATIME_CONVERT_MAP ) ;
2009-01-26 23:18:27 +00:00
}
2010-01-26 03:16:14 +00:00
/* apply unit corrections */
unitFac = ANIM_unit_mapping_get_factor ( ac - > scene , ale - > id , fcu , 0 ) ;
tymin * = unitFac ;
tymax * = unitFac ;
2009-01-26 23:18:27 +00:00
/* try to set cur using these values, if they're more extreme than previously set values */
2009-05-11 11:51:30 +00:00
if ( ( xmin ) & & ( txmin < * xmin ) ) * xmin = txmin ;
if ( ( xmax ) & & ( txmax > * xmax ) ) * xmax = txmax ;
if ( ( ymin ) & & ( tymin < * ymin ) ) * ymin = tymin ;
if ( ( ymax ) & & ( tymax > * ymax ) ) * ymax = tymax ;
2009-01-26 23:18:27 +00:00
}
2011-01-14 05:19:04 +00:00
/* ensure that the extents are not too extreme that view implodes...*/
2011-03-27 17:22:04 +00:00
if ( ( xmin & & xmax ) & & ( fabsf ( * xmax - * xmin ) < 0.1f ) ) * xmax + = 0.1f ;
if ( ( ymin & & ymax ) & & ( fabsf ( * ymax - * ymin ) < 0.1f ) ) * ymax + = 0.1f ;
2011-01-14 05:19:04 +00:00
2009-01-26 23:18:27 +00:00
/* free memory */
BLI_freelistN ( & anim_data ) ;
}
else {
/* set default range */
if ( ac - > scene ) {
if ( xmin ) * xmin = ( float ) ac - > scene - > r . sfra ;
if ( xmax ) * xmax = ( float ) ac - > scene - > r . efra ;
}
else {
if ( xmin ) * xmin = - 5 ;
if ( xmax ) * xmax = 100 ;
}
2009-02-10 10:42:04 +00:00
if ( ymin ) * ymin = - 5 ;
if ( ymax ) * ymax = 5 ;
2009-01-26 23:18:27 +00:00
}
}
/* ****************** Automatic Preview-Range Operator ****************** */
2010-10-15 01:36:14 +00:00
static int graphkeys_previewrange_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-01-26 23:18:27 +00:00
{
bAnimContext ac ;
Scene * scene ;
float min , max ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
if ( ac . scene = = NULL )
return OPERATOR_CANCELLED ;
else
scene = ac . scene ;
/* set the range directly */
2011-03-17 10:02:37 +00:00
get_graph_keyframe_extents ( & ac , & min , & max , NULL , NULL , FALSE ) ;
2010-01-19 20:30:04 +00:00
scene - > r . flag | = SCER_PRV_RANGE ;
2009-01-26 23:18:27 +00:00
scene - > r . psfra = ( int ) floor ( min + 0.5f ) ;
scene - > r . pefra = ( int ) floor ( max + 0.5f ) ;
/* set notifier that things have changed */
// XXX err... there's nothing for frame ranges yet, but this should do fine too
WM_event_add_notifier ( C , NC_SCENE | ND_FRAME , ac . scene ) ;
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_previewrange_set ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Auto-Set Preview Range " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_previewrange_set " ;
2011-01-20 22:22:16 +00:00
ot - > description = " Automatically set Preview Range based on range of keyframes " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
ot - > exec = graphkeys_previewrange_exec ;
2011-02-01 23:51:52 +00:00
ot - > poll = ED_operator_graphedit_active ; // XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier...
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
}
/* ****************** View-All Operator ****************** */
2011-03-17 10:02:37 +00:00
static int graphkeys_viewall ( bContext * C , const short selOnly )
2009-01-26 23:18:27 +00:00
{
bAnimContext ac ;
View2D * v2d ;
float extra ;
2011-03-17 10:02:37 +00:00
2009-01-26 23:18:27 +00:00
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
v2d = & ac . ar - > v2d ;
2011-03-17 10:02:37 +00:00
2009-01-26 23:18:27 +00:00
/* set the horizontal range, with an extra offset so that the extreme keys will be in view */
2011-03-17 10:02:37 +00:00
get_graph_keyframe_extents ( & ac , & v2d - > cur . xmin , & v2d - > cur . xmax , & v2d - > cur . ymin , & v2d - > cur . ymax , selOnly ) ;
2009-02-10 10:42:04 +00:00
extra = 0.1f * ( v2d - > cur . xmax - v2d - > cur . xmin ) ;
2009-01-26 23:18:27 +00:00
v2d - > cur . xmin - = extra ;
v2d - > cur . xmax + = extra ;
2011-03-17 10:02:37 +00:00
2009-02-10 10:42:04 +00:00
extra = 0.1f * ( v2d - > cur . ymax - v2d - > cur . ymin ) ;
2009-01-26 23:18:27 +00:00
v2d - > cur . ymin - = extra ;
v2d - > cur . ymax + = extra ;
2011-03-17 10:02:37 +00:00
2009-01-26 23:18:27 +00:00
/* do View2D syncing */
UI_view2d_sync ( CTX_wm_screen ( C ) , CTX_wm_area ( C ) , v2d , V2D_LOCK_COPY ) ;
2011-03-17 10:02:37 +00:00
2009-01-26 23:18:27 +00:00
/* set notifier that things have changed */
ED_area_tag_redraw ( CTX_wm_area ( C ) ) ;
2011-03-17 10:02:37 +00:00
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2011-03-17 10:02:37 +00:00
/* ......... */
static int graphkeys_viewall_exec ( bContext * C , wmOperator * UNUSED ( op ) )
{
/* whole range */
return graphkeys_viewall ( C , FALSE ) ;
}
2009-01-26 23:18:27 +00:00
2011-03-17 10:02:37 +00:00
static int graphkeys_view_selected_exec ( bContext * C , wmOperator * UNUSED ( op ) )
{
/* only selected */
return graphkeys_viewall ( C , TRUE ) ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_view_all ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " View All " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_view_all " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Reset viewable area to show full keyframe range " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
ot - > exec = graphkeys_viewall_exec ;
2011-02-01 23:51:52 +00:00
ot - > poll = ED_operator_graphedit_active ; // XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier...
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
}
2011-03-17 10:02:37 +00:00
void GRAPH_OT_view_selected ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " View Selected " ;
ot - > idname = " GRAPH_OT_view_selected " ;
ot - > description = " Reset viewable area to show selected keyframe range " ;
/* api callbacks */
ot - > exec = graphkeys_view_selected_exec ;
ot - > poll = ED_operator_graphedit_active ; // XXX: unchecked poll to get fsamples working too, but makes modifier damage trickier...
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2009-04-08 01:07:46 +00:00
/* ******************** Create Ghost-Curves Operator *********************** */
/* This operator samples the data of the selected F-Curves to F-Points, storing them
* as ' ghost curves ' in the active Graph Editor
*/
/* Bake each F-Curve into a set of samples, and store as a ghost curve */
static void create_ghost_curves ( bAnimContext * ac , int start , int end )
{
SpaceIpo * sipo = ( SpaceIpo * ) ac - > sa - > spacedata . first ;
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
/* free existing ghost curves */
free_fcurves ( & sipo - > ghostCurves ) ;
/* sanity check */
if ( start > = end ) {
printf ( " Error: Frame range for Ghost F-Curve creation is inappropriate \n " ) ;
return ;
}
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-04-08 01:07:46 +00:00
ANIM_animdata_filter ( ac , & 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 ) {
FCurve * fcu = ( FCurve * ) ale - > key_data ;
FCurve * gcu = MEM_callocN ( sizeof ( FCurve ) , " Ghost FCurve " ) ;
2009-06-23 13:25:31 +00:00
AnimData * adt = ANIM_nla_mapping_get ( ac , ale ) ;
2009-04-08 01:07:46 +00:00
ChannelDriver * driver = fcu - > driver ;
FPoint * fpt ;
2010-01-26 03:16:14 +00:00
float unitFac ;
2009-04-08 01:07:46 +00:00
int cfra ;
/* disable driver so that it don't muck up the sampling process */
fcu - > driver = NULL ;
2010-01-26 03:16:14 +00:00
/* calculate unit-mapping factor */
unitFac = ANIM_unit_mapping_get_factor ( ac - > scene , ale - > id , fcu , 0 ) ;
2009-04-08 01:07:46 +00:00
/* create samples, but store them in a new curve
* - we cannot use fcurve_store_samples ( ) as that will only overwrite the original curve
*/
gcu - > fpt = fpt = MEM_callocN ( sizeof ( FPoint ) * ( end - start + 1 ) , " Ghost FPoint Samples " ) ;
gcu - > totvert = end - start + 1 ;
/* use the sampling callback at 1-frame intervals from start to end frames */
for ( cfra = start ; cfra < = end ; cfra + + , fpt + + ) {
2009-06-28 07:32:00 +00:00
float cfrae = BKE_nla_tweakedit_remap ( adt , cfra , NLATIME_CONVERT_UNMAP ) ;
2009-06-23 13:25:31 +00:00
fpt - > vec [ 0 ] = cfrae ;
2010-03-05 11:35:15 +00:00
fpt - > vec [ 1 ] = fcurve_samplingcb_evalcurve ( fcu , NULL , cfrae ) * unitFac ;
2009-04-08 01:07:46 +00:00
}
/* set color of ghost curve
* - make the color slightly darker
*/
gcu - > color [ 0 ] = fcu - > color [ 0 ] - 0.07f ;
gcu - > color [ 1 ] = fcu - > color [ 1 ] - 0.07f ;
gcu - > color [ 2 ] = fcu - > color [ 2 ] - 0.07f ;
/* store new ghost curve */
BLI_addtail ( & sipo - > ghostCurves , gcu ) ;
/* restore driver */
fcu - > driver = driver ;
}
/* admin and redraws */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
2010-10-15 01:36:14 +00:00
static int graphkeys_create_ghostcurves_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-04-08 01:07:46 +00:00
{
bAnimContext ac ;
View2D * v2d ;
int start , end ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* ghost curves are snapshots of the visible portions of the curves, so set range to be the visible range */
v2d = & ac . ar - > v2d ;
start = ( int ) v2d - > cur . xmin ;
end = ( int ) v2d - > cur . xmax ;
/* bake selected curves into a ghost curve */
create_ghost_curves ( & ac , start , end ) ;
/* update this editor only */
ED_area_tag_redraw ( CTX_wm_area ( C ) ) ;
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_ghost_curves_create ( wmOperatorType * ot )
2009-04-08 01:07:46 +00:00
{
/* identifiers */
ot - > name = " Create Ghost Curves " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_ghost_curves_create " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Create snapshot (Ghosts) of selected F-Curves as background aid for active Graph Editor " ;
2009-04-08 01:07:46 +00:00
/* api callbacks */
ot - > exec = graphkeys_create_ghostcurves_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_visible_keyframes_poll ;
2009-04-08 01:07:46 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
// todo: add props for start/end frames
}
/* ******************** Clear Ghost-Curves Operator *********************** */
/* This operator clears the 'ghost curves' for the active Graph Editor */
2010-10-15 01:36:14 +00:00
static int graphkeys_clear_ghostcurves_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-04-08 01:07:46 +00:00
{
bAnimContext ac ;
SpaceIpo * sipo ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
sipo = ( SpaceIpo * ) ac . sa - > spacedata . first ;
/* if no ghost curves, don't do anything */
if ( sipo - > ghostCurves . first = = NULL )
return OPERATOR_CANCELLED ;
/* free ghost curves */
free_fcurves ( & sipo - > ghostCurves ) ;
/* update this editor only */
ED_area_tag_redraw ( CTX_wm_area ( C ) ) ;
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_ghost_curves_clear ( wmOperatorType * ot )
2009-04-08 01:07:46 +00:00
{
/* identifiers */
2009-12-07 00:11:17 +00:00
ot - > name = " Clear Ghost Curves " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_ghost_curves_clear " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Clear F-Curve snapshots (Ghosts) for active Graph Editor " ;
2009-04-08 01:07:46 +00:00
/* api callbacks */
ot - > exec = graphkeys_clear_ghostcurves_exec ;
2011-02-01 23:51:52 +00:00
ot - > poll = ED_operator_graphedit_active ;
2009-04-08 01:07:46 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2009-02-10 10:42:04 +00:00
2009-01-26 23:18:27 +00:00
/* ************************************************************************** */
/* GENERAL STUFF */
2009-06-29 03:02:41 +00:00
/* ******************** Insert Keyframes Operator ************************* */
/* defines for insert keyframes tool */
2011-02-14 17:55:27 +00:00
static EnumPropertyItem prop_graphkeys_insertkey_types [ ] = {
2009-06-29 03:02:41 +00:00
{ 1 , " ALL " , 0 , " All Channels " , " " } ,
{ 2 , " SEL " , 0 , " Only Selected Channels " , " " } ,
{ 0 , NULL , 0 , NULL , NULL }
} ;
/* this function is responsible for snapping keyframes to frame-times */
static void insert_graph_keys ( bAnimContext * ac , short mode )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
2010-11-17 12:02:36 +00:00
ReportList * reports = ac - > reports ;
2009-06-29 03:02:41 +00:00
Scene * scene = ac - > scene ;
short flag = 0 ;
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-06-29 03:02:41 +00:00
if ( mode = = 2 ) filter | = ANIMFILTER_SEL ;
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* init keyframing flag */
2009-12-14 12:09:20 +00:00
flag = ANIM_get_keyframing_flags ( scene , 1 ) ;
2009-06-29 03:02:41 +00:00
/* insert keyframes */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
AnimData * adt = ANIM_nla_mapping_get ( ac , ale ) ;
FCurve * fcu = ( FCurve * ) ale - > key_data ;
2011-01-12 03:41:12 +00:00
float cfra ;
2009-06-29 03:02:41 +00:00
/* adjust current frame for NLA-mapping */
if ( adt )
cfra = BKE_nla_tweakedit_remap ( adt , ( float ) CFRA , NLATIME_CONVERT_UNMAP ) ;
else
cfra = ( float ) CFRA ;
/* if there's an id */
if ( ale - > id )
2010-11-17 12:02:36 +00:00
insert_keyframe ( reports , ale - > id , NULL , ( ( fcu - > grp ) ? ( fcu - > grp - > name ) : ( NULL ) ) , fcu - > rna_path , fcu - > array_index , cfra , flag ) ;
2009-06-29 03:02:41 +00:00
else
insert_vert_fcurve ( fcu , cfra , fcu - > curval , 0 ) ;
}
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
static int graphkeys_insertkey_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
short mode ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* which channels to affect? */
mode = RNA_enum_get ( op - > ptr , " type " ) ;
/* insert keyframes */
insert_graph_keys ( & ac , mode ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-06-29 03:02:41 +00:00
return OPERATOR_FINISHED ;
}
2009-11-28 14:37:21 +00:00
void GRAPH_OT_keyframe_insert ( wmOperatorType * ot )
2009-06-29 03:02:41 +00:00
{
/* identifiers */
ot - > name = " Insert Keyframes " ;
2009-11-28 14:37:21 +00:00
ot - > idname = " GRAPH_OT_keyframe_insert " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Insert keyframes for the specified channels " ;
2009-06-29 03:02:41 +00:00
/* api callbacks */
ot - > invoke = WM_menu_invoke ;
ot - > exec = graphkeys_insertkey_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-06-29 03:02:41 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* id-props */
2010-01-15 22:40:33 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , prop_graphkeys_insertkey_types , 0 , " Type " , " " ) ;
2009-06-29 03:02:41 +00:00
}
2009-01-26 23:18:27 +00:00
2009-04-06 12:07:33 +00:00
/* ******************** Click-Insert Keyframes Operator ************************* */
static int graphkeys_click_insert_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
bAnimListElem * ale ;
2009-06-23 13:25:31 +00:00
AnimData * adt ;
2010-01-26 03:16:14 +00:00
FCurve * fcu ;
2009-04-06 12:07:33 +00:00
float frame , val ;
/* get animation context */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* get active F-Curve 'anim-list-element' */
ale = get_active_fcurve_channel ( & ac ) ;
if ( ELEM ( NULL , ale , ale - > data ) ) {
if ( ale ) MEM_freeN ( ale ) ;
return OPERATOR_CANCELLED ;
}
2010-01-26 03:16:14 +00:00
fcu = ale - > data ;
2010-11-17 12:02:36 +00:00
/* when there are F-Modifiers on the curve, only allow adding
* keyframes if these will be visible after doing so . . .
*/
if ( fcurve_is_keyframable ( fcu ) ) {
/* get frame and value from props */
frame = RNA_float_get ( op - > ptr , " frame " ) ;
val = RNA_float_get ( op - > ptr , " value " ) ;
/* apply inverse NLA-mapping to frame to get correct time in un-scaled action */
adt = ANIM_nla_mapping_get ( & ac , ale ) ;
frame = BKE_nla_tweakedit_remap ( adt , frame , NLATIME_CONVERT_UNMAP ) ;
/* apply inverse unit-mapping to value to get correct value for F-Curves */
val * = ANIM_unit_mapping_get_factor ( ac . scene , ale - > id , fcu , 1 ) ;
/* insert keyframe on the specified frame + value */
insert_vert_fcurve ( fcu , frame , val , 0 ) ;
}
else {
/* warn about why this can't happen */
if ( fcu - > fpt )
BKE_report ( op - > reports , RPT_ERROR , " Keyframes cannot be added to sampled F-Curves " ) ;
else if ( fcu - > flag & FCURVE_PROTECTED )
BKE_report ( op - > reports , RPT_ERROR , " Active F-Curve is not editable " ) ;
else
BKE_report ( op - > reports , RPT_ERROR , " Remove F-Modifiers from F-Curve to add keyframes " ) ;
}
2009-04-06 12:07:33 +00:00
/* free temp data */
MEM_freeN ( ale ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-04-06 12:07:33 +00:00
/* done */
return OPERATOR_FINISHED ;
}
static int graphkeys_click_insert_invoke ( bContext * C , wmOperator * op , wmEvent * evt )
{
bAnimContext ac ;
ARegion * ar ;
View2D * v2d ;
int mval [ 2 ] ;
float x , y ;
/* get animation context */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* store mouse coordinates in View2D space, into the operator's properties */
ar = ac . ar ;
v2d = & ar - > v2d ;
mval [ 0 ] = ( evt - > x - ar - > winrct . xmin ) ;
mval [ 1 ] = ( evt - > y - ar - > winrct . ymin ) ;
UI_view2d_region_to_view ( v2d , mval [ 0 ] , mval [ 1 ] , & x , & y ) ;
RNA_float_set ( op - > ptr , " frame " , x ) ;
RNA_float_set ( op - > ptr , " value " , y ) ;
/* run exec now */
return graphkeys_click_insert_exec ( C , op ) ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_click_insert ( wmOperatorType * ot )
2009-04-06 12:07:33 +00:00
{
/* identifiers */
ot - > name = " Click-Insert Keyframes " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_click_insert " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Insert new keyframe at the cursor position for the active F-Curve " ;
2009-04-06 12:07:33 +00:00
/* api callbacks */
ot - > invoke = graphkeys_click_insert_invoke ;
ot - > exec = graphkeys_click_insert_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_active_fcurve_poll ;
2009-04-06 12:07:33 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
RNA_def_float ( ot - > srna , " frame " , 1.0f , - FLT_MAX , FLT_MAX , " Frame Number " , " Frame to insert keyframe on " , 0 , 100 ) ;
RNA_def_float ( ot - > srna , " value " , 1.0f , - FLT_MAX , FLT_MAX , " Value " , " Value for keyframe on " , 0 , 100 ) ;
}
2009-01-26 23:18:27 +00:00
/* ******************** Copy/Paste Keyframes Operator ************************* */
2009-02-24 11:18:24 +00:00
/* NOTE: the backend code for this is shared with the dopesheet editor */
2009-01-26 23:18:27 +00:00
static short copy_graph_keys ( bAnimContext * ac )
{
ListBase anim_data = { NULL , NULL } ;
2009-02-24 11:18:24 +00:00
int filter , ok = 0 ;
2009-01-26 23:18:27 +00:00
/* clear buffer first */
2009-02-24 11:18:24 +00:00
free_anim_copybuf ( ) ;
2009-01-26 23:18:27 +00:00
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
2009-02-24 11:18:24 +00:00
/* copy keyframes */
ok = copy_animedit_keys ( ac , & anim_data ) ;
2009-01-26 23:18:27 +00:00
2009-02-24 11:18:24 +00:00
/* clean up */
2009-01-26 23:18:27 +00:00
BLI_freelistN ( & anim_data ) ;
2009-02-24 16:51:55 +00:00
return ok ;
}
2009-02-24 11:18:24 +00:00
2010-12-14 15:14:16 +00:00
static short paste_graph_keys ( bAnimContext * ac ,
const eKeyPasteOffset offset_mode , const eKeyMergeMode merge_mode )
2009-02-24 11:18:24 +00:00
{
2009-01-26 23:18:27 +00:00
ListBase anim_data = { NULL , NULL } ;
2009-02-24 11:18:24 +00:00
int filter , ok = 0 ;
2009-01-26 23:18:27 +00:00
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
2009-02-24 11:18:24 +00:00
/* paste keyframes */
2010-12-14 15:14:16 +00:00
ok = paste_animedit_keys ( ac , & anim_data , offset_mode , merge_mode ) ;
2009-01-26 23:18:27 +00:00
2009-02-24 11:18:24 +00:00
/* clean up */
2009-01-26 23:18:27 +00:00
BLI_freelistN ( & anim_data ) ;
2009-02-24 16:51:55 +00:00
return ok ;
2009-01-26 23:18:27 +00:00
}
/* ------------------- */
static int graphkeys_copy_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* copy keyframes */
2009-01-27 05:04:23 +00:00
if ( copy_graph_keys ( & ac ) ) {
2009-02-24 11:23:04 +00:00
BKE_report ( op - > reports , RPT_ERROR , " No keyframes copied to keyframes copy/paste buffer " ) ;
return OPERATOR_CANCELLED ;
2009-01-26 23:18:27 +00:00
}
2009-07-10 10:48:25 +00:00
/* just return - no operator needed here (no changes) */
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_copy ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Copy Keyframes " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_copy " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Copy selected keyframes to the copy/paste buffer " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
ot - > exec = graphkeys_copy_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
}
static int graphkeys_paste_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
2010-12-14 15:14:16 +00:00
const eKeyPasteOffset offset_mode = RNA_enum_get ( op - > ptr , " offset " ) ;
const eKeyMergeMode merge_mode = RNA_enum_get ( op - > ptr , " merge " ) ;
2009-01-26 23:18:27 +00:00
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
2010-12-09 11:49:38 +00:00
if ( ac . reports = = NULL ) {
ac . reports = op - > reports ;
}
2009-01-26 23:18:27 +00:00
/* paste keyframes */
2010-12-14 15:14:16 +00:00
if ( paste_graph_keys ( & ac , offset_mode , merge_mode ) ) {
2009-02-24 11:23:04 +00:00
return OPERATOR_CANCELLED ;
2009-01-26 23:18:27 +00:00
}
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_paste ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Paste Keyframes " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_paste " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Paste keyframes from copy/paste buffer for the selected channels, starting on the current frame " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
2010-12-14 15:14:16 +00:00
// ot->invoke= WM_operator_props_popup; // better wait for graph redo panel
2009-01-26 23:18:27 +00:00
ot - > exec = graphkeys_paste_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2010-12-14 15:14:16 +00:00
RNA_def_enum ( ot - > srna , " offset " , keyframe_paste_offset_items , KEYFRAME_PASTE_OFFSET_CFRA_START , " Offset " , " Paste time offset of keys " ) ;
RNA_def_enum ( ot - > srna , " merge " , keyframe_paste_merge_items , KEYFRAME_PASTE_MERGE_MIX , " Type " , " Method of merking pasted keys and existing " ) ;
2009-01-26 23:18:27 +00:00
}
2009-02-20 11:17:33 +00:00
/* ******************** Duplicate Keyframes Operator ************************* */
static void duplicate_graph_keys ( bAnimContext * ac )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-02-20 11:17:33 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* loop through filtered data and delete selected keys */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
duplicate_fcurve_keys ( ( FCurve * ) ale - > key_data ) ;
}
/* free filtered list */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
2010-10-15 01:36:14 +00:00
static int graphkeys_duplicate_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-02-20 11:17:33 +00:00
{
bAnimContext ac ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* duplicate keyframes */
duplicate_graph_keys ( & ac ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-02-20 11:17:33 +00:00
return OPERATOR_FINISHED ;
}
2010-10-15 01:36:14 +00:00
static int graphkeys_duplicate_invoke ( bContext * C , wmOperator * op , wmEvent * UNUSED ( event ) )
2009-02-20 11:17:33 +00:00
{
graphkeys_duplicate_exec ( C , op ) ;
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_duplicate ( wmOperatorType * ot )
2009-02-20 11:17:33 +00:00
{
/* identifiers */
ot - > name = " Duplicate Keyframes " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_duplicate " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Make a copy of all selected keyframes " ;
2009-02-20 11:17:33 +00:00
/* api callbacks */
ot - > invoke = graphkeys_duplicate_invoke ;
ot - > exec = graphkeys_duplicate_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-02-20 11:17:33 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* to give to transform */
2011-04-01 08:51:12 +00:00
RNA_def_enum ( ot - > srna , " mode " , transform_mode_types , TFM_TRANSLATION , " Mode " , " " ) ;
2009-02-20 11:17:33 +00:00
}
2009-01-26 23:18:27 +00:00
/* ******************** Delete Keyframes Operator ************************* */
static void delete_graph_keys ( bAnimContext * ac )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* loop through filtered data and delete selected keys */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
2009-12-04 03:51:52 +00:00
FCurve * fcu = ( FCurve * ) ale - > key_data ;
2009-12-06 09:37:31 +00:00
AnimData * adt = ale - > adt ;
2009-12-04 03:51:52 +00:00
/* delete selected keyframes only */
delete_fcurve_keys ( fcu ) ;
/* Only delete curve too if it won't be doing anything anymore */
if ( ( fcu - > totvert = = 0 ) & & ( list_has_suitable_fmodifier ( & fcu - > modifiers , 0 , FMI_TYPE_GENERATE_CURVE ) = = 0 ) )
2009-12-06 09:37:31 +00:00
ANIM_fcurve_delete_from_animdata ( ac , adt , fcu ) ;
2009-01-26 23:18:27 +00:00
}
/* free filtered list */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
2010-10-15 01:36:14 +00:00
static int graphkeys_delete_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-01-26 23:18:27 +00:00
{
bAnimContext ac ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* delete keyframes */
delete_graph_keys ( & ac ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_delete ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Delete Keyframes " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_delete " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Remove all selected keyframes " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
2009-01-28 09:55:36 +00:00
ot - > invoke = WM_operator_confirm ;
2009-01-26 23:18:27 +00:00
ot - > exec = graphkeys_delete_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
}
/* ******************** Clean Keyframes Operator ************************* */
static void clean_graph_keys ( bAnimContext * ac , float thresh )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* loop through filtered data and clean curves */
for ( ale = anim_data . first ; ale ; ale = ale - > next )
clean_fcurve ( ( FCurve * ) ale - > key_data , thresh ) ;
/* free temp data */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
static int graphkeys_clean_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
float thresh ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* get cleaning threshold */
thresh = RNA_float_get ( op - > ptr , " threshold " ) ;
/* clean keyframes */
clean_graph_keys ( & ac , thresh ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_clean ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Clean Keyframes " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_clean " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Simplify F-Curves by removing closely spaced keyframes " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
//ot->invoke= // XXX we need that number popup for this!
ot - > exec = graphkeys_clean_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
/* properties */
2010-02-07 23:39:44 +00:00
ot - > prop = RNA_def_float ( ot - > srna , " threshold " , 0.001f , 0.0f , FLT_MAX , " Threshold " , " " , 0.0f , 1000.0f ) ;
2009-01-26 23:18:27 +00:00
}
2009-03-01 11:27:31 +00:00
/* ******************** Bake F-Curve Operator *********************** */
/* This operator bakes the data of the selected F-Curves to F-Points */
/* Bake each F-Curve into a set of samples */
static void bake_graph_curves ( bAnimContext * ac , int start , int end )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-03-01 11:27:31 +00:00
ANIM_animdata_filter ( ac , & 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 ) {
FCurve * fcu = ( FCurve * ) ale - > key_data ;
ChannelDriver * driver = fcu - > driver ;
/* disable driver so that it don't muck up the sampling process */
fcu - > driver = NULL ;
/* create samples */
fcurve_store_samples ( fcu , NULL , start , end , fcurve_samplingcb_evalcurve ) ;
/* restore driver */
fcu - > driver = driver ;
}
/* admin and redraws */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
2010-10-15 01:36:14 +00:00
static int graphkeys_bake_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-03-01 11:27:31 +00:00
{
bAnimContext ac ;
Scene * scene = NULL ;
int start , end ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* for now, init start/end from preview-range extents */
// TODO: add properties for this
scene = ac . scene ;
start = PSFRA ;
end = PEFRA ;
/* bake keyframes */
bake_graph_curves ( & ac , start , end ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
// NOTE: some distinction between order/number of keyframes and type should be made?
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-03-01 11:27:31 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_bake ( wmOperatorType * ot )
2009-03-01 11:27:31 +00:00
{
/* identifiers */
ot - > name = " Bake Curve " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_bake " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Bake selected F-Curves to a set of sampled points defining a similar curve " ;
2009-03-01 11:27:31 +00:00
/* api callbacks */
ot - > invoke = WM_operator_confirm ; // FIXME...
ot - > exec = graphkeys_bake_exec ;
2009-10-26 11:10:04 +00:00
ot - > poll = graphop_selected_fcurve_poll ;
2009-03-01 11:27:31 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
// todo: add props for start/end frames
}
2010-01-01 05:09:30 +00:00
/* ******************** Sound Bake F-Curve Operator *********************** */
/* This operator bakes the given sound to the selected F-Curves */
/* ------------------- */
/* Custom data storage passed to the F-Sample-ing function,
* which provides the necessary info for baking the sound
*/
typedef struct tSoundBakeInfo {
2010-01-26 03:16:14 +00:00
float * samples ;
2010-01-01 05:09:30 +00:00
int length ;
int cfra ;
} tSoundBakeInfo ;
/* ------------------- */
/* Sampling callback used to determine the value from the sound to
* save in the F - Curve at the specified frame
*/
2010-10-16 08:03:28 +00:00
static float fcurve_samplingcb_sound ( FCurve * UNUSED ( fcu ) , void * data , float evaltime )
2010-01-01 05:09:30 +00:00
{
tSoundBakeInfo * sbi = ( tSoundBakeInfo * ) data ;
int position = evaltime - sbi - > cfra ;
if ( ( position < 0 ) | | ( position > = sbi - > length ) )
return 0.0f ;
return sbi - > samples [ position ] ;
}
/* ------------------- */
static int graphkeys_sound_bake_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
tSoundBakeInfo sbi ;
Scene * scene = NULL ;
int start , end ;
char path [ FILE_MAX ] ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
2010-06-14 03:52:10 +00:00
RNA_string_get ( op - > ptr , " filepath " , path ) ;
2010-01-01 05:09:30 +00:00
scene = ac . scene ; /* current scene */
/* store necessary data for the baking steps */
sbi . samples = AUD_readSoundBuffer ( path ,
RNA_float_get ( op - > ptr , " low " ) ,
RNA_float_get ( op - > ptr , " high " ) ,
RNA_float_get ( op - > ptr , " attack " ) ,
RNA_float_get ( op - > ptr , " release " ) ,
RNA_float_get ( op - > ptr , " threshold " ) ,
2010-01-01 18:45:21 +00:00
RNA_boolean_get ( op - > ptr , " accumulate " ) ,
2010-08-19 17:10:43 +00:00
RNA_boolean_get ( op - > ptr , " use_additive " ) ,
2010-01-01 18:45:21 +00:00
RNA_boolean_get ( op - > ptr , " square " ) ,
RNA_float_get ( op - > ptr , " sthreshold " ) ,
2010-01-01 05:09:30 +00:00
FPS , & sbi . length ) ;
if ( sbi . samples = = NULL ) {
BKE_report ( op - > reports , RPT_ERROR , " Unsupported audio format " ) ;
return OPERATOR_CANCELLED ;
}
/* determine extents of the baking */
sbi . cfra = start = CFRA ;
end = CFRA + sbi . length - 1 ;
/* filter anim channels */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2010-01-01 05:09:30 +00:00
ANIM_animdata_filter ( & ac , & anim_data , filter , ac . data , ac . datatype ) ;
/* loop through all selected F-Curves, replacing its data with the sound samples */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
FCurve * fcu = ( FCurve * ) ale - > key_data ;
2010-01-26 03:16:14 +00:00
2010-01-01 05:09:30 +00:00
/* sample the sound */
fcurve_store_samples ( fcu , & sbi , start , end , fcurve_samplingcb_sound ) ;
}
/* free sample data */
free ( sbi . samples ) ;
/* admin and redraws */
BLI_freelistN ( & anim_data ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
/* set notifier that 'keyframes' have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2010-01-01 05:09:30 +00:00
return OPERATOR_FINISHED ;
}
static int graphkeys_sound_bake_invoke ( bContext * C , wmOperator * op , wmEvent * event )
{
bAnimContext ac ;
/* verify editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
return WM_operator_filesel ( C , op , event ) ;
}
void GRAPH_OT_sound_bake ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Bake Sound to F-Curves " ;
ot - > idname = " GRAPH_OT_sound_bake " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Bakes a sound wave to selected F-Curves " ;
2010-01-01 05:09:30 +00:00
/* api callbacks */
ot - > invoke = graphkeys_sound_bake_invoke ;
ot - > exec = graphkeys_sound_bake_exec ;
ot - > poll = graphop_selected_fcurve_poll ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
2010-07-01 19:28:45 +00:00
WM_operator_properties_filesel ( ot , FOLDERFILE | SOUNDFILE | MOVIEFILE , FILE_SPECIAL , FILE_OPENFILE , WM_FILESEL_FILEPATH ) ;
2010-01-01 05:09:30 +00:00
RNA_def_float ( ot - > srna , " low " , 0.0f , 0.0 , 100000.0 , " Lowest frequency " , " " , 0.1 , 1000.00 ) ;
RNA_def_float ( ot - > srna , " high " , 100000.0 , 0.0 , 100000.0 , " Highest frequency " , " " , 0.1 , 1000.00 ) ;
RNA_def_float ( ot - > srna , " attack " , 0.005 , 0.0 , 2.0 , " Attack time " , " " , 0.01 , 0.1 ) ;
RNA_def_float ( ot - > srna , " release " , 0.2 , 0.0 , 5.0 , " Release time " , " " , 0.01 , 0.2 ) ;
RNA_def_float ( ot - > srna , " threshold " , 0.0 , 0.0 , 1.0 , " Threshold " , " " , 0.01 , 0.1 ) ;
2010-01-01 18:45:21 +00:00
RNA_def_boolean ( ot - > srna , " accumulate " , 0 , " Accumulate " , " " ) ;
2010-08-19 17:10:43 +00:00
RNA_def_boolean ( ot - > srna , " use_additive " , 0 , " Additive " , " " ) ;
2010-01-01 18:45:21 +00:00
RNA_def_boolean ( ot - > srna , " square " , 0 , " Square " , " " ) ;
RNA_def_float ( ot - > srna , " sthreshold " , 0.1 , 0.0 , 1.0 , " Square Threshold " , " " , 0.01 , 0.1 ) ;
2010-01-01 05:09:30 +00:00
}
2009-01-26 23:18:27 +00:00
/* ******************** Sample Keyframes Operator *********************** */
2009-03-01 11:27:31 +00:00
/* This operator 'bakes' the values of the curve into new keyframes between pairs
* of selected keyframes . It is useful for creating keyframes for tweaking overlap .
*/
2009-01-26 23:18:27 +00:00
/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
static void sample_graph_keys ( bAnimContext * ac )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* loop through filtered data and add keys between selected keyframes on every frame */
2009-09-04 04:27:06 +00:00
for ( ale = anim_data . first ; ale ; ale = ale - > next )
sample_fcurve ( ( FCurve * ) ale - > key_data ) ;
2009-01-26 23:18:27 +00:00
/* admin and redraws */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
2010-10-15 01:36:14 +00:00
static int graphkeys_sample_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-01-26 23:18:27 +00:00
{
bAnimContext ac ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* sample keyframes */
sample_graph_keys ( & ac ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_sample ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Sample Keyframes " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_sample " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Add keyframes on every frame between the selected keyframes " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
ot - > exec = graphkeys_sample_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
}
2009-01-28 09:55:36 +00:00
2009-01-26 23:18:27 +00:00
/* ************************************************************************** */
/* SETTINGS STUFF */
/* ******************** Set Extrapolation-Type Operator *********************** */
/* defines for set extrapolation-type for selected keyframes tool */
2011-02-14 17:55:27 +00:00
static EnumPropertyItem prop_graphkeys_expo_types [ ] = {
2009-06-16 00:52:21 +00:00
{ FCURVE_EXTRAPOLATE_CONSTANT , " CONSTANT " , 0 , " Constant Extrapolation " , " " } ,
{ FCURVE_EXTRAPOLATE_LINEAR , " LINEAR " , 0 , " Linear Extrapolation " , " " } ,
{ 0 , NULL , 0 , NULL , NULL }
2009-01-26 23:18:27 +00:00
} ;
/* this function is responsible for setting extrapolation mode for keyframes */
static void setexpo_graph_keys ( bAnimContext * ac , short mode )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
/* filter data */
2010-10-16 03:13:40 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* loop through setting mode per F-Curve */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
FCurve * fcu = ( FCurve * ) ale - > data ;
fcu - > extend = mode ;
}
/* cleanup */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
static int graphkeys_expo_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
short mode ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* get handle setting mode */
mode = RNA_enum_get ( op - > ptr , " type " ) ;
/* set handle type */
setexpo_graph_keys ( & ac , mode ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframe properties have changed */
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME_PROP , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_extrapolation_type ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Set Keyframe Extrapolation " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_extrapolation_type " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Set extrapolation mode for selected F-Curves " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
ot - > invoke = WM_menu_invoke ;
ot - > exec = graphkeys_expo_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
/* id-props */
2010-01-15 22:40:33 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , prop_graphkeys_expo_types , 0 , " Type " , " " ) ;
2009-01-26 23:18:27 +00:00
}
/* ******************** Set Interpolation-Type Operator *********************** */
/* this function is responsible for setting interpolation mode for keyframes */
static void setipo_graph_keys ( bAnimContext * ac , short mode )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
2010-04-02 12:02:39 +00:00
KeyframeEditFunc set_cb = ANIM_editkeyframes_ipo ( mode ) ;
2009-01-26 23:18:27 +00:00
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* loop through setting BezTriple interpolation
2010-04-02 12:02:39 +00:00
* Note : we do not supply KeyframeEditData to the looper yet . Currently that ' s not necessary here . . .
2009-01-26 23:18:27 +00:00
*/
for ( ale = anim_data . first ; ale ; ale = ale - > next )
2010-04-02 12:02:39 +00:00
ANIM_fcurve_keyframes_loop ( NULL , ale - > key_data , NULL , set_cb , calchandles_fcurve ) ;
2009-01-26 23:18:27 +00:00
/* cleanup */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
static int graphkeys_ipo_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
short mode ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* get handle setting mode */
mode = RNA_enum_get ( op - > ptr , " type " ) ;
/* set handle type */
setipo_graph_keys ( & ac , mode ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframe properties have changed */
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME_PROP , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_interpolation_type ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Set Keyframe Interpolation " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_interpolation_type " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Set interpolation mode for the F-Curve segments starting from the selected keyframes " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
ot - > invoke = WM_menu_invoke ;
ot - > exec = graphkeys_ipo_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
/* id-props */
2010-01-15 22:40:33 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , beztriple_interpolation_mode_items , 0 , " Type " , " " ) ;
2009-01-26 23:18:27 +00:00
}
/* ******************** Set Handle-Type Operator *********************** */
2010-02-01 11:45:24 +00:00
/* ------------------- */
2009-01-26 23:18:27 +00:00
/* this function is responsible for setting handle-type of selected keyframes */
static void sethandles_graph_keys ( bAnimContext * ac , short mode )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
2010-02-02 21:16:28 +00:00
2010-04-02 12:02:39 +00:00
KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles ( mode ) ;
KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok ( BEZT_OK_SELECTED ) ;
2009-01-26 23:18:27 +00:00
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* loop through setting flags for handles
2010-04-02 12:02:39 +00:00
* Note : we do not supply KeyframeEditData to the looper yet . Currently that ' s not necessary here . . .
2009-01-26 23:18:27 +00:00
*/
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
2010-02-02 21:16:28 +00:00
FCurve * fcu = ( FCurve * ) ale - > key_data ;
2010-02-01 11:45:24 +00:00
2010-02-02 21:16:28 +00:00
/* any selected keyframes for editing? */
2010-04-02 12:02:39 +00:00
if ( ANIM_fcurve_keyframes_loop ( NULL , fcu , NULL , sel_cb , NULL ) ) {
2010-02-02 21:16:28 +00:00
/* for auto/auto-clamped, toggle the auto-handles flag on the F-Curve */
if ( mode = = HD_AUTO_ANIM )
fcu - > flag | = FCURVE_AUTO_HANDLES ;
else if ( mode = = HD_AUTO )
fcu - > flag & = ~ FCURVE_AUTO_HANDLES ;
2009-01-26 23:18:27 +00:00
2010-02-02 21:16:28 +00:00
/* change type of selected handles */
2010-04-02 12:02:39 +00:00
ANIM_fcurve_keyframes_loop ( NULL , fcu , NULL , edit_cb , calchandles_fcurve ) ;
2010-02-02 21:16:28 +00:00
}
2009-01-26 23:18:27 +00:00
}
/* cleanup */
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
static int graphkeys_handletype_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
short mode ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* get handle setting mode */
mode = RNA_enum_get ( op - > ptr , " type " ) ;
/* set handle type */
2010-02-02 21:16:28 +00:00
sethandles_graph_keys ( & ac , mode ) ;
2009-01-26 23:18:27 +00:00
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2010-02-01 11:45:24 +00:00
/* set notifier that keyframe properties have changed */
2009-07-10 10:48:25 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME_PROP , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2010-12-14 10:52:38 +00:00
void GRAPH_OT_handle_type ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
2010-12-14 10:17:13 +00:00
/* sync with editcurve_handle_type_items */
static EnumPropertyItem graphkeys_handle_type_items [ ] = {
{ HD_AUTO , " AUTO " , 0 , " Automatic " , " Handles that are automatically adjusted upon moving the keyframe. Whole curve " } ,
{ HD_VECT , " VECTOR " , 0 , " Vector " , " " } ,
{ HD_ALIGN , " ALIGNED " , 0 , " Aligned " , " " } ,
{ HD_FREE , " FREE_ALIGN " , 0 , " Free " , " " } ,
{ HD_AUTO_ANIM , " ANIM_CLAMPED " , 0 , " Auto Clamped " , " Auto handles clamped to not overshoot. Whole curve " } ,
{ 0 , NULL , 0 , NULL , NULL } } ;
2009-01-26 23:18:27 +00:00
/* identifiers */
ot - > name = " Set Keyframe Handle Type " ;
2010-12-14 10:52:38 +00:00
ot - > idname = " GRAPH_OT_handle_type " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Set type of handle for selected keyframes " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
2010-12-14 10:17:13 +00:00
ot - > invoke = WM_menu_invoke ;
2009-01-26 23:18:27 +00:00
ot - > exec = graphkeys_handletype_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
/* id-props */
2010-02-01 11:45:24 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , graphkeys_handle_type_items , 0 , " Type " , " " ) ;
2009-01-26 23:18:27 +00:00
}
/* ************************************************************************** */
/* TRANSFORM STUFF */
2009-03-07 04:24:28 +00:00
/* ***************** 'Euler Filter' Operator **************************** */
/* Euler filter tools (as seen in Maya), are necessary for working with 'baked'
* rotation curves ( with Euler rotations ) . The main purpose of such tools is to
* resolve any discontinuities that may arise in the curves due to the clamping
* of values to - 180 degrees to 180 degrees .
*/
2009-03-15 10:39:02 +00:00
/* set of three euler-rotation F-Curves */
typedef struct tEulerFilter {
2011-03-25 03:58:21 +00:00
struct tEulerFilter * next , * prev ;
2009-03-15 10:39:02 +00:00
ID * id ; /* ID-block which owns the channels */
2011-03-25 03:58:21 +00:00
FCurve * ( fcurves [ 3 ] ) ; /* 3 Pointers to F-Curves */
char * rna_path ; /* Pointer to one of the RNA Path's used by one of the F-Curves */
2009-03-15 10:39:02 +00:00
} tEulerFilter ;
2009-03-07 04:24:28 +00:00
static int graphkeys_euler_filter_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
2009-03-15 10:39:02 +00:00
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
ListBase eulers = { NULL , NULL } ;
2011-03-25 03:58:21 +00:00
tEulerFilter * euf = NULL ;
int groups = 0 , failed = 0 ;
2009-03-07 04:24:28 +00:00
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* The process is done in two passes:
* 1 ) Sets of three related rotation curves are identified from the selected channels ,
* and are stored as a single ' operation unit ' for the next step
* 2 ) Each set of three F - Curves is processed for each keyframe , with the values being
2011-03-25 03:58:21 +00:00
* processed as necessary
2009-03-07 04:24:28 +00:00
*/
2009-03-15 10:39:02 +00:00
/* step 1: extract only the rotation f-curves */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS ) ;
2009-03-15 10:39:02 +00:00
ANIM_animdata_filter ( & ac , & anim_data , filter , ac . data , ac . datatype ) ;
2009-03-07 04:24:28 +00:00
2009-03-15 10:39:02 +00:00
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
FCurve * fcu = ( FCurve * ) ale - > data ;
/* check if this is an appropriate F-Curve
* - only rotation curves
* - for pchan curves , make sure we ' re only using the euler curves
*/
2011-03-25 03:58:21 +00:00
if ( strstr ( fcu - > rna_path , " rotation_euler " ) = = NULL )
2009-03-15 10:39:02 +00:00
continue ;
2011-03-25 03:58:21 +00:00
else if ( ELEM3 ( fcu - > array_index , 0 , 1 , 2 ) = = 0 ) {
BKE_reportf ( op - > reports , RPT_WARNING ,
" Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d) " ,
( ale - > id ) ? ale - > id - > name : " <No ID> " , fcu - > rna_path , fcu - > array_index ) ;
continue ;
}
2009-03-15 10:39:02 +00:00
2011-03-25 03:58:21 +00:00
/* optimisation: assume that xyz curves will always be stored consecutively,
* so if the paths or the ID ' s don ' t match up , then a curve needs to be added
* to a new group
2009-03-15 10:39:02 +00:00
*/
2011-03-25 03:58:21 +00:00
if ( ( euf ) & & ( euf - > id = = ale - > id ) & & ( strcmp ( euf - > rna_path , fcu - > rna_path ) = = 0 ) ) {
/* this should be fine to add to the existing group then */
euf - > fcurves [ fcu - > array_index ] = fcu ;
2009-03-15 10:39:02 +00:00
}
2.5 - Assorted Animation UI/Editing Tweaks
Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)
* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying.
* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...
Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
2009-09-27 04:22:04 +00:00
else {
/* just add to a new block */
euf = MEM_callocN ( sizeof ( tEulerFilter ) , " tEulerFilter " ) ;
BLI_addtail ( & eulers , euf ) ;
2011-03-25 03:58:21 +00:00
groups + + ;
2.5 - Assorted Animation UI/Editing Tweaks
Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)
* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying.
* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...
Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
2009-09-27 04:22:04 +00:00
euf - > id = ale - > id ;
2011-03-25 03:58:21 +00:00
euf - > rna_path = fcu - > rna_path ; /* this should be safe, since we're only using it for a short time */
2.5 - Assorted Animation UI/Editing Tweaks
Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)
* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying.
* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...
Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
2009-09-27 04:22:04 +00:00
euf - > fcurves [ fcu - > array_index ] = fcu ;
}
2009-03-15 10:39:02 +00:00
}
2.5 - Assorted Animation UI/Editing Tweaks
Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)
* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying.
* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...
Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
2009-09-27 04:22:04 +00:00
BLI_freelistN ( & anim_data ) ;
2009-03-07 04:24:28 +00:00
2011-03-25 03:58:21 +00:00
if ( groups = = 0 ) {
BKE_report ( op - > reports , RPT_WARNING , " No Euler Rotation F-Curves to fix up " ) ;
return OPERATOR_CANCELLED ;
}
2.5 - Assorted Animation UI/Editing Tweaks
Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)
* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying.
* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...
Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
2009-09-27 04:22:04 +00:00
/* step 2: go through each set of curves, processing the values at each keyframe
* - it is assumed that there must be a full set of keyframes at each keyframe position
*/
for ( euf = eulers . first ; euf ; euf = euf - > next ) {
2011-03-25 03:58:21 +00:00
int f ;
/* sanity check: ensure that there are enough F-Curves to work on in this group */
// TODO: also enforce assumption that there be a full set of keyframes at each position by ensuring that totvert counts are same?
if ( ELEM3 ( NULL , euf - > fcurves [ 0 ] , euf - > fcurves [ 1 ] , euf - > fcurves [ 2 ] ) ) {
/* report which components are missing */
BKE_reportf ( op - > reports , RPT_WARNING ,
" Missing %s%s%s component(s) of euler rotation for ID='%s' and RNA-Path='%s' " ,
( euf - > fcurves [ 0 ] = = NULL ) ? " X " : " " ,
( euf - > fcurves [ 1 ] = = NULL ) ? " Y " : " " ,
( euf - > fcurves [ 2 ] = = NULL ) ? " Z " : " " ,
euf - > id - > name , euf - > rna_path ) ;
/* keep track of number of failed sets, and carry on to next group */
failed + + ;
continue ;
}
2.5 - Assorted Animation UI/Editing Tweaks
Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)
* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying.
* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...
Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
2009-09-27 04:22:04 +00:00
2011-03-25 03:58:21 +00:00
/* simple method: just treat any difference between keys of greater than 180 degrees as being a flip */
// FIXME: there are more complicated methods that will be needed to fix more cases than just some
for ( f = 0 ; f < 3 ; f + + ) {
FCurve * fcu = euf - > fcurves [ f ] ;
BezTriple * bezt , * prev = NULL ;
unsigned int i ;
/* skip if not enough vets to do a decent analysis of... */
if ( fcu - > totvert < = 2 )
continue ;
/* prev follows bezt, bezt = "current" point to be fixed */
for ( i = 0 , bezt = fcu - > bezt ; i < fcu - > totvert ; i + + , prev = bezt , bezt + + ) {
/* our method depends on determining a "difference" from the previous vert */
if ( prev = = NULL )
continue ;
/* > 180 degree flip? */
if ( fabs ( prev - > vec [ 1 ] [ 1 ] - bezt - > vec [ 1 ] [ 1 ] ) > = M_PI ) {
/* 360 degrees to add/subtract frame value until difference is acceptably small that there's no more flip */
2011-03-27 17:22:04 +00:00
const float fac = 2.0f * ( float ) M_PI ;
2011-03-25 03:58:21 +00:00
if ( prev - > vec [ 1 ] [ 1 ] > bezt - > vec [ 1 ] [ 1 ] ) {
2011-03-27 17:22:04 +00:00
while ( fabsf ( bezt - > vec [ 1 ] [ 1 ] - prev - > vec [ 1 ] [ 1 ] ) > = ( float ) M_PI ) {
2011-03-25 03:58:21 +00:00
bezt - > vec [ 0 ] [ 1 ] + = fac ;
bezt - > vec [ 1 ] [ 1 ] + = fac ;
bezt - > vec [ 2 ] [ 1 ] + = fac ;
}
}
else /* if (prev->vec[1][1] < bezt->vec[1][1]) */ {
2011-03-27 17:22:04 +00:00
while ( fabsf ( bezt - > vec [ 1 ] [ 1 ] - prev - > vec [ 1 ] [ 1 ] ) > = ( float ) M_PI ) {
2011-03-25 03:58:21 +00:00
bezt - > vec [ 0 ] [ 1 ] - = fac ;
bezt - > vec [ 1 ] [ 1 ] - = fac ;
bezt - > vec [ 2 ] [ 1 ] - = fac ;
}
}
}
}
}
2.5 - Assorted Animation UI/Editing Tweaks
Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)
* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying.
* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...
Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
2009-09-27 04:22:04 +00:00
}
BLI_freelistN ( & eulers ) ;
2011-03-25 03:58:21 +00:00
/* updates + finishing warnings */
if ( failed = = groups ) {
BKE_report ( op - > reports , RPT_ERROR ,
" No Euler Rotations could be corrected. Ensure each rotation has keys for all components, and that F-Curves for these are in consecutive XYZ order and selected. " ) ;
return OPERATOR_CANCELLED ;
}
else {
if ( failed ) {
BKE_report ( op - > reports , RPT_ERROR ,
" Some Euler Rotations couldn't be corrected due to missing/unselected/out-of-order F-Curves. Ensure each rotation has keys for all components, and that F-Curves for these are in consecutive XYZ order and selected. " ) ;
}
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
/* set notifier that keyframes have changed */
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
/* done at last */
return OPERATOR_FINISHED ;
}
2009-03-07 04:24:28 +00:00
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_euler_filter ( wmOperatorType * ot )
2009-03-07 04:24:28 +00:00
{
/* identifiers */
2011-03-25 03:58:21 +00:00
ot - > name = " Euler Discontinuity Filter " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_euler_filter " ;
2011-03-25 03:58:21 +00:00
ot - > description = " Fixes the most common causes of gimbal lock in the selected Euler Rotation F-Curves " ;
2009-03-07 04:24:28 +00:00
/* api callbacks */
ot - > exec = graphkeys_euler_filter_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-03-07 04:24:28 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2009-06-22 04:23:06 +00:00
/* ***************** Jump to Selected Frames Operator *********************** */
2009-01-26 23:18:27 +00:00
/* snap current-frame indicator to 'average time' of selected keyframe */
2010-10-15 01:36:14 +00:00
static int graphkeys_framejump_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-01-26 23:18:27 +00:00
{
bAnimContext ac ;
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
2010-04-02 12:02:39 +00:00
KeyframeEditData ked ;
2009-01-26 23:18:27 +00:00
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* init edit data */
2010-04-02 12:02:39 +00:00
memset ( & ked , 0 , sizeof ( KeyframeEditData ) ) ;
2009-01-26 23:18:27 +00:00
/* loop over action data, averaging values */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( & ac , & anim_data , filter , ac . data , ac . datatype ) ;
2009-06-23 13:25:31 +00:00
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
AnimData * adt = ANIM_nla_mapping_get ( & ac , ale ) ;
2010-01-26 03:16:14 +00:00
/* apply unit corrections */
2010-01-26 09:25:32 +00:00
ANIM_unit_mapping_apply_fcurve ( ac . scene , ale - > id , ale - > key_data , ANIM_UNITCONV_ONLYKEYS ) ;
2010-01-26 03:16:14 +00:00
2009-06-23 13:25:31 +00:00
if ( adt ) {
2010-01-15 10:34:39 +00:00
ANIM_nla_mapping_apply_fcurve ( adt , ale - > key_data , 0 , 1 ) ;
2010-04-02 12:02:39 +00:00
ANIM_fcurve_keyframes_loop ( & ked , ale - > key_data , NULL , bezt_calc_average , NULL ) ;
2010-01-15 10:34:39 +00:00
ANIM_nla_mapping_apply_fcurve ( adt , ale - > key_data , 1 , 1 ) ;
2009-06-23 13:25:31 +00:00
}
else
2010-04-02 12:02:39 +00:00
ANIM_fcurve_keyframes_loop ( & ked , ale - > key_data , NULL , bezt_calc_average , NULL ) ;
2009-06-23 13:25:31 +00:00
2010-01-26 03:16:14 +00:00
/* unapply unit corrections */
2010-01-26 09:25:32 +00:00
ANIM_unit_mapping_apply_fcurve ( ac . scene , ale - > id , ale - > key_data , ANIM_UNITCONV_RESTORE | ANIM_UNITCONV_ONLYKEYS ) ;
2009-06-23 13:25:31 +00:00
}
2009-01-26 23:18:27 +00:00
BLI_freelistN ( & anim_data ) ;
2009-10-22 09:15:56 +00:00
/* set the new current frame and cursor values, based on the average time and value */
2010-04-02 12:02:39 +00:00
if ( ked . i1 ) {
2009-10-22 09:15:56 +00:00
SpaceIpo * sipo = ac . sa - > spacedata . first ;
2009-01-26 23:18:27 +00:00
Scene * scene = ac . scene ;
2009-10-22 09:15:56 +00:00
/* take the average values, rounding to the nearest int for the current frame */
2010-04-02 12:02:39 +00:00
CFRA = ( int ) floor ( ( ked . f1 / ked . i1 ) + 0.5f ) ;
2010-06-27 05:39:55 +00:00
SUBFRA = 0.f ;
2010-04-02 12:02:39 +00:00
sipo - > cursorVal = ked . f2 / ( float ) ked . i1 ;
2009-01-26 23:18:27 +00:00
}
2009-04-10 03:34:20 +00:00
/* set notifier that things have changed */
2009-01-26 23:18:27 +00:00
WM_event_add_notifier ( C , NC_SCENE | ND_FRAME , ac . scene ) ;
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_frame_jump ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
2009-06-22 04:23:06 +00:00
ot - > name = " Jump to Frame " ;
ot - > idname = " GRAPH_OT_frame_jump " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Set the current frame to the average frame of the selected keyframes " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
2009-06-22 04:23:06 +00:00
ot - > exec = graphkeys_framejump_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_visible_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
}
/* ******************** Snap Keyframes Operator *********************** */
/* defines for snap keyframes tool */
2011-02-14 17:55:27 +00:00
static EnumPropertyItem prop_graphkeys_snap_types [ ] = {
2009-10-20 12:04:56 +00:00
{ GRAPHKEYS_SNAP_CFRA , " CFRA " , 0 , " Current Frame " , " " } ,
{ GRAPHKEYS_SNAP_VALUE , " VALUE " , 0 , " Cursor Value " , " " } ,
2009-06-16 00:52:21 +00:00
{ GRAPHKEYS_SNAP_NEAREST_FRAME , " NEAREST_FRAME " , 0 , " Nearest Frame " , " " } , // XXX as single entry?
{ GRAPHKEYS_SNAP_NEAREST_SECOND , " NEAREST_SECOND " , 0 , " Nearest Second " , " " } , // XXX as single entry?
{ GRAPHKEYS_SNAP_NEAREST_MARKER , " NEAREST_MARKER " , 0 , " Nearest Marker " , " " } ,
{ GRAPHKEYS_SNAP_HORIZONTAL , " HORIZONTAL " , 0 , " Flatten Handles " , " " } ,
{ 0 , NULL , 0 , NULL , NULL }
2009-01-26 23:18:27 +00:00
} ;
/* this function is responsible for snapping keyframes to frame-times */
static void snap_graph_keys ( bAnimContext * ac , short mode )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
2010-04-02 12:02:39 +00:00
KeyframeEditData ked ;
KeyframeEditFunc edit_cb ;
2009-01-26 23:18:27 +00:00
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* get beztriple editing callbacks */
edit_cb = ANIM_editkeyframes_snap ( mode ) ;
2010-04-02 12:02:39 +00:00
memset ( & ked , 0 , sizeof ( KeyframeEditData ) ) ;
ked . scene = ac - > scene ;
2009-05-09 02:37:12 +00:00
if ( mode = = GRAPHKEYS_SNAP_NEAREST_MARKER ) {
2010-04-02 12:02:39 +00:00
ked . list . first = ( ac - > markers ) ? ac - > markers - > first : NULL ;
ked . list . last = ( ac - > markers ) ? ac - > markers - > last : NULL ;
2009-05-09 02:37:12 +00:00
}
2009-10-20 12:04:56 +00:00
else if ( mode = = GRAPHKEYS_SNAP_VALUE ) {
SpaceIpo * sipo = ( SpaceIpo * ) ac - > sa - > spacedata . first ;
2010-04-02 12:02:39 +00:00
ked . f1 = ( sipo ) ? sipo - > cursorVal : 0.0f ;
2009-10-20 12:04:56 +00:00
}
2009-01-26 23:18:27 +00:00
/* snap keyframes */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
2009-06-23 13:25:31 +00:00
AnimData * adt = ANIM_nla_mapping_get ( ac , ale ) ;
2009-01-26 23:18:27 +00:00
2010-01-26 03:16:14 +00:00
/* apply unit corrections */
2010-01-26 09:25:32 +00:00
ANIM_unit_mapping_apply_fcurve ( ac - > scene , ale - > id , ale - > key_data , 0 ) ;
2010-01-26 03:16:14 +00:00
2009-06-23 13:25:31 +00:00
if ( adt ) {
2010-01-15 10:34:39 +00:00
ANIM_nla_mapping_apply_fcurve ( adt , ale - > key_data , 0 , 1 ) ;
2010-04-02 12:02:39 +00:00
ANIM_fcurve_keyframes_loop ( & ked , ale - > key_data , NULL , edit_cb , calchandles_fcurve ) ;
2010-01-15 10:34:39 +00:00
ANIM_nla_mapping_apply_fcurve ( adt , ale - > key_data , 1 , 1 ) ;
2009-01-26 23:18:27 +00:00
}
else
2010-04-02 12:02:39 +00:00
ANIM_fcurve_keyframes_loop ( & ked , ale - > key_data , NULL , edit_cb , calchandles_fcurve ) ;
2010-01-26 03:16:14 +00:00
/* apply unit corrections */
2010-01-26 09:25:32 +00:00
ANIM_unit_mapping_apply_fcurve ( ac - > scene , ale - > id , ale - > key_data , ANIM_UNITCONV_RESTORE ) ;
2009-01-26 23:18:27 +00:00
}
2010-01-26 03:16:14 +00:00
2009-01-26 23:18:27 +00:00
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
static int graphkeys_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_graph_keys ( & ac , mode ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_snap ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Snap Keys " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_snap " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Snap selected keyframes to the chosen times/values " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
ot - > invoke = WM_menu_invoke ;
ot - > exec = graphkeys_snap_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
/* id-props */
2010-01-15 22:40:33 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , prop_graphkeys_snap_types , 0 , " Type " , " " ) ;
2009-01-26 23:18:27 +00:00
}
/* ******************** Mirror Keyframes Operator *********************** */
/* defines for mirror keyframes tool */
2011-02-14 17:55:27 +00:00
static EnumPropertyItem prop_graphkeys_mirror_types [ ] = {
2009-10-22 09:07:19 +00:00
{ GRAPHKEYS_MIRROR_CFRA , " CFRA " , 0 , " By Times over Current Frame " , " " } ,
{ GRAPHKEYS_MIRROR_VALUE , " VALUE " , 0 , " By Values over Cursor Value " , " " } ,
2009-07-01 01:17:58 +00:00
{ GRAPHKEYS_MIRROR_YAXIS , " YAXIS " , 0 , " By Times over Time=0 " , " " } ,
{ GRAPHKEYS_MIRROR_XAXIS , " XAXIS " , 0 , " By Values over Value=0 " , " " } ,
{ GRAPHKEYS_MIRROR_MARKER , " MARKER " , 0 , " By Times over First Selected Marker " , " " } ,
2009-06-16 00:52:21 +00:00
{ 0 , NULL , 0 , NULL , NULL }
2009-01-26 23:18:27 +00:00
} ;
/* this function is responsible for mirroring keyframes */
static void mirror_graph_keys ( bAnimContext * ac , short mode )
{
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter ;
2010-04-02 12:02:39 +00:00
KeyframeEditData ked ;
KeyframeEditFunc edit_cb ;
2009-01-26 23:18:27 +00:00
/* get beztriple editing callbacks */
edit_cb = ANIM_editkeyframes_mirror ( mode ) ;
2010-04-02 12:02:39 +00:00
memset ( & ked , 0 , sizeof ( KeyframeEditData ) ) ;
ked . scene = ac - > scene ;
2009-01-26 23:18:27 +00:00
/* for 'first selected marker' mode, need to find first selected marker first! */
// XXX should this be made into a helper func in the API?
2009-01-28 06:32:47 +00:00
if ( mode = = GRAPHKEYS_MIRROR_MARKER ) {
2009-01-26 23:18:27 +00:00
TimeMarker * marker = NULL ;
/* find first selected marker */
2011-01-06 04:35:57 +00:00
marker = ED_markers_get_first_selected ( ac - > markers ) ;
2009-01-26 23:18:27 +00:00
/* store marker's time (if available) */
if ( marker )
2010-04-02 12:02:39 +00:00
ked . f1 = ( float ) marker - > frame ;
2009-01-26 23:18:27 +00:00
else
return ;
}
2009-10-22 09:07:19 +00:00
else if ( mode = = GRAPHKEYS_MIRROR_VALUE ) {
SpaceIpo * sipo = ( SpaceIpo * ) ac - > sa - > spacedata . first ;
2010-04-02 12:02:39 +00:00
ked . f1 = ( sipo ) ? sipo - > cursorVal : 0.0f ;
2009-10-22 09:07:19 +00:00
}
2009-01-26 23:18:27 +00:00
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-26 23:18:27 +00:00
ANIM_animdata_filter ( ac , & anim_data , filter , ac - > data , ac - > datatype ) ;
/* mirror keyframes */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
2009-06-23 13:25:31 +00:00
AnimData * adt = ANIM_nla_mapping_get ( ac , ale ) ;
2009-01-26 23:18:27 +00:00
2010-01-26 03:16:14 +00:00
/* apply unit corrections */
2010-01-26 09:25:32 +00:00
ANIM_unit_mapping_apply_fcurve ( ac - > scene , ale - > id , ale - > key_data , ANIM_UNITCONV_ONLYKEYS ) ;
2010-01-26 03:16:14 +00:00
2009-06-23 13:25:31 +00:00
if ( adt ) {
2010-01-15 10:34:39 +00:00
ANIM_nla_mapping_apply_fcurve ( adt , ale - > key_data , 0 , 1 ) ;
2010-04-02 12:02:39 +00:00
ANIM_fcurve_keyframes_loop ( & ked , ale - > key_data , NULL , edit_cb , calchandles_fcurve ) ;
2010-01-15 10:34:39 +00:00
ANIM_nla_mapping_apply_fcurve ( adt , ale - > key_data , 1 , 1 ) ;
2009-01-26 23:18:27 +00:00
}
else
2010-04-02 12:02:39 +00:00
ANIM_fcurve_keyframes_loop ( & ked , ale - > key_data , NULL , edit_cb , calchandles_fcurve ) ;
2010-01-26 03:16:14 +00:00
/* unapply unit corrections */
2010-01-26 09:25:32 +00:00
ANIM_unit_mapping_apply_fcurve ( ac - > scene , ale - > id , ale - > key_data , ANIM_UNITCONV_ONLYKEYS | ANIM_UNITCONV_RESTORE ) ;
2009-01-26 23:18:27 +00:00
}
2010-01-26 03:16:14 +00:00
2009-01-26 23:18:27 +00:00
BLI_freelistN ( & anim_data ) ;
}
/* ------------------- */
static int graphkeys_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 mirroring mode */
mode = RNA_enum_get ( op - > ptr , " type " ) ;
/* mirror keyframes */
mirror_graph_keys ( & ac , mode ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-01-26 23:18:27 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_mirror ( wmOperatorType * ot )
2009-01-26 23:18:27 +00:00
{
/* identifiers */
ot - > name = " Mirror Keys " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_mirror " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Flip selected keyframes over the selected mirror line " ;
2009-01-26 23:18:27 +00:00
/* api callbacks */
ot - > invoke = WM_menu_invoke ;
ot - > exec = graphkeys_mirror_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-26 23:18:27 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-26 23:18:27 +00:00
/* id-props */
2010-01-15 22:40:33 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , prop_graphkeys_mirror_types , 0 , " Type " , " " ) ;
2009-01-26 23:18:27 +00:00
}
2009-01-28 09:55:36 +00:00
/* ******************** Smooth Keyframes Operator *********************** */
2010-10-15 01:36:14 +00:00
static int graphkeys_smooth_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2009-01-28 09:55:36 +00:00
{
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 ;
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-01-28 09:55:36 +00:00
ANIM_animdata_filter ( & ac , & anim_data , filter , ac . data , ac . datatype ) ;
/* smooth keyframes */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
/* For now, we can only smooth by flattening handles AND smoothing curve values.
* Perhaps the mode argument could be removed , as that functionality is offerred through
* Snap - > Flatten Handles anyway .
*/
smooth_fcurve ( ale - > key_data ) ;
}
BLI_freelistN ( & anim_data ) ;
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
2009-07-10 10:48:25 +00:00
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-01-28 09:55:36 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_smooth ( wmOperatorType * ot )
2009-01-28 09:55:36 +00:00
{
/* identifiers */
ot - > name = " Smooth Keys " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_smooth " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Apply weighted moving means to make selected F-Curves less bumpy " ;
2009-01-28 09:55:36 +00:00
/* api callbacks */
ot - > exec = graphkeys_smooth_exec ;
2009-07-02 01:01:18 +00:00
ot - > poll = graphop_editable_keyframes_poll ;
2009-01-28 09:55:36 +00:00
/* flags */
2009-01-31 19:40:40 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2009-01-28 09:55:36 +00:00
}
2009-01-26 23:18:27 +00:00
/* ************************************************************************** */
2009-03-15 10:39:02 +00:00
/* F-CURVE MODIFIERS */
2009-07-02 06:41:10 +00:00
/* ******************** Add F-Modifier Operator *********************** */
2009-03-15 10:39:02 +00:00
2009-07-03 01:10:46 +00:00
/* present a special customised popup menu for this, with some filtering */
2010-10-15 01:36:14 +00:00
static int graph_fmodifier_add_invoke ( bContext * C , wmOperator * op , wmEvent * UNUSED ( event ) )
2009-07-03 01:10:46 +00:00
{
uiPopupMenu * pup ;
uiLayout * layout ;
int i ;
2011-02-27 18:03:19 +00:00
pup = uiPupMenuBegin ( C , " Add F-Curve Modifier " , ICON_NONE ) ;
2009-07-03 01:10:46 +00:00
layout = uiPupMenuLayout ( pup ) ;
/* start from 1 to skip the 'Invalid' modifier type */
for ( i = 1 ; i < FMODIFIER_NUM_TYPES ; i + + ) {
FModifierTypeInfo * fmi = get_fmodifier_typeinfo ( i ) ;
2009-09-25 12:20:31 +00:00
PointerRNA props_ptr ;
2009-07-03 01:10:46 +00:00
/* check if modifier is valid for this context */
if ( fmi = = NULL )
continue ;
2009-09-25 12:20:31 +00:00
/* create operator menu item with relevant properties filled in */
2011-02-27 18:03:19 +00:00
props_ptr = uiItemFullO ( layout , " GRAPH_OT_fmodifier_add " , fmi - > name , ICON_NONE , NULL , WM_OP_EXEC_REGION_WIN , UI_ITEM_O_RETURN_PROPS ) ;
2009-09-25 12:20:31 +00:00
/* the only thing that gets set from the menu is the type of F-Modifier to add */
RNA_enum_set ( & props_ptr , " type " , i ) ;
/* the following properties are just repeats of existing ones... */
RNA_boolean_set ( & props_ptr , " only_active " , RNA_boolean_get ( op - > ptr , " only_active " ) ) ;
2009-07-03 01:10:46 +00:00
}
uiItemS ( layout ) ;
uiPupMenuEnd ( C , pup ) ;
return OPERATOR_CANCELLED ;
}
2009-03-15 10:39:02 +00:00
static int graph_fmodifier_add_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
2009-09-25 12:20:31 +00:00
ListBase anim_data = { NULL , NULL } ;
2009-03-15 10:39:02 +00:00
bAnimListElem * ale ;
2009-09-25 12:20:31 +00:00
int filter ;
2009-03-15 10:39:02 +00:00
short type ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* get type of modifier to add */
type = RNA_enum_get ( op - > ptr , " type " ) ;
2009-09-25 12:20:31 +00:00
/* filter data */
2010-05-20 05:18:27 +00:00
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS ) ;
2009-09-25 12:20:31 +00:00
if ( RNA_boolean_get ( op - > ptr , " only_active " ) )
2011-01-14 05:19:04 +00:00
filter | = ANIMFILTER_ACTIVE ; // FIXME: enforce in this case only a single channel to get handled?
2009-09-25 12:20:31 +00:00
else
2010-01-25 23:11:01 +00:00
filter | = ( ANIMFILTER_SEL | ANIMFILTER_CURVEVISIBLE ) ;
2009-09-25 12:20:31 +00:00
ANIM_animdata_filter ( & ac , & anim_data , filter , ac . data , ac . datatype ) ;
2010-03-18 13:04:46 +00:00
/* add f-modifier to each curve */
2009-09-25 12:20:31 +00:00
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
FCurve * fcu = ( FCurve * ) ale - > data ;
FModifier * fcm ;
/* add F-Modifier of specified type to active F-Curve, and make it the active one */
fcm = add_fmodifier ( & fcu - > modifiers , type ) ;
if ( fcm )
set_active_fmodifier ( & fcu - > modifiers , fcm ) ;
2011-01-14 05:19:04 +00:00
else {
2009-09-25 12:20:31 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Modifier couldn't be added. See console for details. " ) ;
break ;
}
2009-03-18 10:58:18 +00:00
}
2009-09-25 12:20:31 +00:00
BLI_freelistN ( & anim_data ) ;
2009-03-15 10:39:02 +00:00
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
/* set notifier that things have changed */
2009-07-10 10:48:25 +00:00
// FIXME: this really isn't the best description for it...
WM_event_add_notifier ( C , NC_ANIMATION , NULL ) ;
2009-03-15 10:39:02 +00:00
return OPERATOR_FINISHED ;
}
2009-06-22 04:23:06 +00:00
void GRAPH_OT_fmodifier_add ( wmOperatorType * ot )
2009-03-15 10:39:02 +00:00
{
/* identifiers */
ot - > name = " Add F-Curve Modifier " ;
2009-06-22 04:23:06 +00:00
ot - > idname = " GRAPH_OT_fmodifier_add " ;
2010-02-10 21:15:44 +00:00
ot - > description = " Add F-Modifiers to the selected F-Curves " ;
2009-03-15 10:39:02 +00:00
/* api callbacks */
2009-07-03 01:10:46 +00:00
ot - > invoke = graph_fmodifier_add_invoke ;
2009-03-15 10:39:02 +00:00
ot - > exec = graph_fmodifier_add_exec ;
2.5 - Assorted Animation UI/Editing Tweaks
Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)
* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying.
* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...
Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
2009-09-27 04:22:04 +00:00
ot - > poll = graphop_selected_fcurve_poll ;
2009-03-15 10:39:02 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* id-props */
2010-02-07 23:39:44 +00:00
ot - > prop = RNA_def_enum ( ot - > srna , " type " , fmodifier_type_items , 0 , " Type " , " " ) ;
2009-09-25 12:20:31 +00:00
RNA_def_boolean ( ot - > srna , " only_active " , 1 , " Only Active " , " Only add F-Modifier to active F-Curve. " ) ;
2009-03-15 10:39:02 +00:00
}
2010-03-18 13:04:46 +00:00
/* ******************** Copy F-Modifiers Operator *********************** */
static int graph_fmodifier_copy_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
bAnimListElem * ale ;
short ok = 0 ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* clear buffer first */
free_fmodifiers_copybuf ( ) ;
/* get the active F-Curve */
ale = get_active_fcurve_channel ( & ac ) ;
/* if this exists, call the copy F-Modifiers API function */
if ( ale & & ale - > data ) {
FCurve * fcu = ( FCurve * ) ale - > data ;
// TODO: when 'active' vs 'all' boolean is added, change last param!
ok = ANIM_fmodifiers_copy_to_buf ( & fcu - > modifiers , 0 ) ;
/* free temp data now */
MEM_freeN ( ale ) ;
}
/* successful or not? */
if ( ok = = 0 ) {
BKE_report ( op - > reports , RPT_ERROR , " No F-Modifiers available to be copied " ) ;
return OPERATOR_CANCELLED ;
}
else
return OPERATOR_FINISHED ;
}
void GRAPH_OT_fmodifier_copy ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Copy F-Modifiers " ;
ot - > idname = " GRAPH_OT_fmodifier_copy " ;
ot - > description = " Copy the F-Modifier(s) of the active F-Curve. " ;
/* api callbacks */
ot - > exec = graph_fmodifier_copy_exec ;
ot - > poll = graphop_active_fcurve_poll ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* id-props */
//ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one");
}
/* ******************** Paste F-Modifiers Operator *********************** */
static int graph_fmodifier_paste_exec ( bContext * C , wmOperator * op )
{
bAnimContext ac ;
ListBase anim_data = { NULL , NULL } ;
bAnimListElem * ale ;
int filter , ok = 0 ;
/* get editor data */
if ( ANIM_animdata_get_context ( C , & ac ) = = 0 )
return OPERATOR_CANCELLED ;
/* filter data */
filter = ( ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY ) ;
ANIM_animdata_filter ( & ac , & anim_data , filter , ac . data , ac . datatype ) ;
/* paste modifiers */
for ( ale = anim_data . first ; ale ; ale = ale - > next ) {
FCurve * fcu = ( FCurve * ) ale - > data ;
// TODO: do we want to replace existing modifiers? add user pref for that!
ok + = ANIM_fmodifiers_paste_from_buf ( & fcu - > modifiers , 0 ) ;
}
/* clean up */
BLI_freelistN ( & anim_data ) ;
/* successful or not? */
if ( ok ) {
/* validate keyframes after editing */
ANIM_editkeyframes_refresh ( & ac ) ;
/* set notifier that keyframes have changed */
2010-06-18 04:39:32 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2010-03-18 13:04:46 +00:00
return OPERATOR_FINISHED ;
}
else {
BKE_report ( op - > reports , RPT_ERROR , " No F-Modifiers to paste " ) ;
return OPERATOR_CANCELLED ;
}
}
void GRAPH_OT_fmodifier_paste ( wmOperatorType * ot )
{
/* identifiers */
ot - > name = " Paste F-Modifiers " ;
ot - > idname = " GRAPH_OT_fmodifier_paste " ;
ot - > description = " Add copied F-Modifiers to the selected F-Curves " ;
/* api callbacks */
ot - > exec = graph_fmodifier_paste_exec ;
2011-05-24 12:24:05 +00:00
ot - > poll = graphop_active_fcurve_poll ;
2010-03-18 13:04:46 +00:00
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
}
2009-03-15 10:39:02 +00:00
/* ************************************************************************** */