2009-01-26 23:18:27 +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,
|
|
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2008 Blender Foundation
|
|
|
|
*
|
|
|
|
* Contributor(s): Joshua Leung
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <float.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_arithb.h"
|
|
|
|
|
|
|
|
#include "DNA_anim_types.h"
|
|
|
|
#include "DNA_action_types.h"
|
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_camera_types.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_space_types.h"
|
|
|
|
#include "DNA_constraint_types.h"
|
|
|
|
#include "DNA_key_types.h"
|
|
|
|
#include "DNA_lamp_types.h"
|
|
|
|
#include "DNA_material_types.h"
|
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
#include "DNA_gpencil_types.h"
|
|
|
|
#include "DNA_windowmanager_types.h"
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_define.h"
|
|
|
|
|
|
|
|
#include "BKE_action.h"
|
|
|
|
#include "BKE_depsgraph.h"
|
|
|
|
#include "BKE_fcurve.h"
|
|
|
|
#include "BKE_key.h"
|
|
|
|
#include "BKE_material.h"
|
2009-06-23 13:25:31 +00:00
|
|
|
#include "BKE_nla.h"
|
2009-01-26 23:18:27 +00:00
|
|
|
#include "BKE_object.h"
|
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
|
|
|
|
#include "UI_view2d.h"
|
|
|
|
|
|
|
|
#include "ED_anim_api.h"
|
|
|
|
#include "ED_keyframing.h"
|
|
|
|
#include "ED_keyframes_draw.h"
|
|
|
|
#include "ED_keyframes_edit.h"
|
2009-05-08 12:51:36 +00:00
|
|
|
#include "ED_markers.h"
|
2009-01-26 23:18:27 +00:00
|
|
|
#include "ED_screen.h"
|
|
|
|
#include "ED_space_api.h"
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************** */
|
|
|
|
/* KEYFRAMES STUFF */
|
|
|
|
|
|
|
|
/* ******************** Deselect All Operator ***************************** */
|
|
|
|
/* This operator works in one of three ways:
|
|
|
|
* 1) (de)select all (AKEY) - test if select all or deselect all
|
|
|
|
* 2) invert all (CTRL-IKEY) - invert selection of all keyframes
|
|
|
|
* 3) (de)select all - no testing is done; only for use internal tools as normal function...
|
|
|
|
*/
|
|
|
|
|
2009-04-08 01:07:46 +00:00
|
|
|
/* Deselects keyframes in the Graph Editor
|
2009-01-26 23:18:27 +00:00
|
|
|
* - This is called by the deselect all operator, as well as other ones!
|
|
|
|
*
|
|
|
|
* - test: check if select or deselect all
|
|
|
|
* - sel: how to select keyframes
|
|
|
|
* 0 = deselect
|
|
|
|
* 1 = select
|
|
|
|
* 2 = invert
|
|
|
|
*/
|
|
|
|
static void deselect_graph_keys (bAnimContext *ac, short test, short sel)
|
|
|
|
{
|
|
|
|
ListBase anim_data = {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
|
|
|
int filter;
|
|
|
|
|
|
|
|
BeztEditData bed;
|
|
|
|
BeztEditFunc test_cb, sel_cb;
|
|
|
|
|
|
|
|
/* determine type-based settings */
|
2009-01-27 05:04:23 +00:00
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* filter data */
|
|
|
|
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
|
|
|
|
|
|
|
/* init BezTriple looping data */
|
|
|
|
memset(&bed, 0, sizeof(BeztEditData));
|
|
|
|
test_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
|
|
|
|
|
|
|
|
/* See if we should be selecting or deselecting */
|
|
|
|
if (test) {
|
|
|
|
for (ale= anim_data.first; ale; ale= ale->next) {
|
2009-01-27 05:04:23 +00:00
|
|
|
if (ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, test_cb, NULL)) {
|
|
|
|
sel= SELECT_SUBTRACT;
|
|
|
|
break;
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert sel to selectmode, and use that to get editor */
|
|
|
|
sel_cb= ANIM_editkeyframes_select(sel);
|
|
|
|
|
|
|
|
/* Now set the flags */
|
2009-02-09 10:33:05 +00:00
|
|
|
for (ale= anim_data.first; ale; ale= ale->next) {
|
|
|
|
FCurve *fcu= (FCurve *)ale->key_data;
|
|
|
|
|
|
|
|
/* Keyframes First */
|
2009-01-27 05:04:23 +00:00
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, sel_cb, NULL);
|
2009-02-09 10:33:05 +00:00
|
|
|
|
2009-09-25 10:52:29 +00:00
|
|
|
/* deactivate the F-Curve, and deselect if deselecting keyframes.
|
|
|
|
* otherwise select the F-Curve too since we've selected all the keyframes
|
|
|
|
*/
|
2009-05-18 02:23:20 +00:00
|
|
|
if (sel == SELECT_SUBTRACT)
|
|
|
|
fcu->flag &= ~FCURVE_SELECTED;
|
2009-09-25 10:52:29 +00:00
|
|
|
else
|
|
|
|
fcu->flag |= FCURVE_SELECTED;
|
2009-02-09 10:33:05 +00:00
|
|
|
fcu->flag &= ~FCURVE_ACTIVE;
|
|
|
|
}
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
BLI_freelistN(&anim_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------- */
|
|
|
|
|
|
|
|
static int graphkeys_deselectall_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
bAnimContext ac;
|
|
|
|
|
|
|
|
/* get editor data */
|
|
|
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
/* 'standard' behaviour - check if selected, then apply relevant selection */
|
|
|
|
if (RNA_boolean_get(op->ptr, "invert"))
|
|
|
|
deselect_graph_keys(&ac, 0, SELECT_INVERT);
|
|
|
|
else
|
|
|
|
deselect_graph_keys(&ac, 1, SELECT_ADD);
|
|
|
|
|
2009-04-10 03:34:20 +00:00
|
|
|
/* set notifier that things have changed */
|
2009-07-10 10:48:25 +00:00
|
|
|
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2009-06-22 04:23:06 +00:00
|
|
|
void GRAPH_OT_select_all_toggle (wmOperatorType *ot)
|
2009-01-26 23:18:27 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Select All";
|
2009-06-22 04:23:06 +00:00
|
|
|
ot->idname= "GRAPH_OT_select_all_toggle";
|
2009-07-11 10:20:48 +00:00
|
|
|
ot->description= "Toggle selection of all keyframes.";
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= graphkeys_deselectall_exec;
|
2009-07-02 01:01:18 +00:00
|
|
|
ot->poll= graphop_visible_keyframes_poll;
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
|
|
|
|
|
|
|
|
/* props */
|
|
|
|
RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************** Border Select Operator **************************** */
|
|
|
|
/* This operator currently works in one of three ways:
|
2009-01-27 11:09:30 +00:00
|
|
|
* -> BKEY - 1) all keyframes within region are selected (validation with BEZT_OK_REGION)
|
2009-01-26 23:18:27 +00:00
|
|
|
* -> ALT-BKEY - depending on which axis of the region was larger...
|
2009-01-27 11:09:30 +00:00
|
|
|
* -> 2) x-axis, so select all frames within frame range (validation with BEZT_OK_FRAMERANGE)
|
|
|
|
* -> 3) y-axis, so select all frames within channels that region included (validation with BEZT_OK_VALUERANGE)
|
2009-01-26 23:18:27 +00:00
|
|
|
*/
|
|
|
|
|
2009-01-27 11:09:30 +00:00
|
|
|
/* Borderselect only selects keyframes now, as overshooting handles often get caught too,
|
|
|
|
* which means that they may be inadvertantly moved as well.
|
|
|
|
* Also, for convenience, handles should get same status as keyframe (if it was within bounds)
|
|
|
|
*/
|
|
|
|
static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, short selectmode)
|
2009-01-26 23:18:27 +00:00
|
|
|
{
|
|
|
|
ListBase anim_data = {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
|
|
|
int filter;
|
|
|
|
|
|
|
|
BeztEditData bed;
|
|
|
|
BeztEditFunc ok_cb, select_cb;
|
|
|
|
View2D *v2d= &ac->ar->v2d;
|
|
|
|
rctf rectf;
|
|
|
|
|
|
|
|
/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
|
2009-01-27 11:09:30 +00:00
|
|
|
UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
|
|
|
|
UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* filter data */
|
2009-01-27 11:09:30 +00:00
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE);
|
2009-01-26 23:18:27 +00:00
|
|
|
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
|
|
|
|
|
|
|
/* get beztriple editing/validation funcs */
|
|
|
|
select_cb= ANIM_editkeyframes_select(selectmode);
|
2009-01-27 11:09:30 +00:00
|
|
|
ok_cb= ANIM_editkeyframes_ok(mode);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* init editing data */
|
|
|
|
memset(&bed, 0, sizeof(BeztEditData));
|
2009-01-27 11:31:30 +00:00
|
|
|
bed.data= &rectf;
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* loop over data, doing border select */
|
|
|
|
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-09-11 09:09:54 +00:00
|
|
|
FCurve *fcu= (FCurve *)ale->key_data;
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* set horizontal range (if applicable) */
|
2009-01-27 11:09:30 +00:00
|
|
|
if (mode != BEZT_OK_VALUERANGE) {
|
2009-01-26 23:18:27 +00:00
|
|
|
/* if channel is mapped in NLA, apply correction */
|
2009-06-23 13:25:31 +00:00
|
|
|
if (adt) {
|
2009-06-28 07:32:00 +00:00
|
|
|
bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
|
|
|
|
bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
bed.f1= rectf.xmin;
|
|
|
|
bed.f2= rectf.xmax;
|
|
|
|
}
|
|
|
|
}
|
2009-01-27 11:14:02 +00:00
|
|
|
else {
|
|
|
|
bed.f1= rectf.ymin;
|
|
|
|
bed.f2= rectf.ymax;
|
|
|
|
}
|
2009-01-26 23:18:27 +00:00
|
|
|
|
2009-01-27 11:09:30 +00:00
|
|
|
/* select keyframes that are in the appropriate places */
|
2009-09-11 09:09:54 +00:00
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, fcu, ok_cb, select_cb, NULL);
|
|
|
|
|
|
|
|
/* select the curve too
|
|
|
|
* NOTE: this should really only happen if the curve got touched...
|
|
|
|
*/
|
2009-09-25 10:52:29 +00:00
|
|
|
if (selectmode == SELECT_ADD) {
|
2009-09-11 09:09:54 +00:00
|
|
|
fcu->flag |= FCURVE_SELECTED;
|
2009-09-25 10:52:29 +00:00
|
|
|
}
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* cleanup */
|
|
|
|
BLI_freelistN(&anim_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------- */
|
|
|
|
|
|
|
|
static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
bAnimContext ac;
|
|
|
|
rcti rect;
|
|
|
|
short mode=0, selectmode=0;
|
|
|
|
|
|
|
|
/* get editor data */
|
|
|
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
|
|
|
return OPERATOR_CANCELLED;
|
2009-11-06 22:51:08 +00:00
|
|
|
|
|
|
|
if(RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT)
|
|
|
|
selectmode= SELECT_ADD;
|
|
|
|
else
|
|
|
|
selectmode= SELECT_SUBTRACT;
|
|
|
|
|
2009-01-26 23:18:27 +00:00
|
|
|
/* get settings from operator */
|
|
|
|
rect.xmin= RNA_int_get(op->ptr, "xmin");
|
|
|
|
rect.ymin= RNA_int_get(op->ptr, "ymin");
|
|
|
|
rect.xmax= RNA_int_get(op->ptr, "xmax");
|
|
|
|
rect.ymax= RNA_int_get(op->ptr, "ymax");
|
|
|
|
|
|
|
|
/* selection 'mode' depends on whether borderselect region only matters on one axis */
|
|
|
|
if (RNA_boolean_get(op->ptr, "axis_range")) {
|
|
|
|
/* mode depends on which axis of the range is larger to determine which axis to use
|
|
|
|
* - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
|
|
|
|
* - the frame-range select option is favoured over the channel one (x over y), as frame-range one is often
|
|
|
|
* used for tweaking timing when "blocking", while channels is not that useful...
|
|
|
|
*/
|
|
|
|
if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin))
|
2009-01-27 11:09:30 +00:00
|
|
|
mode= BEZT_OK_FRAMERANGE;
|
|
|
|
else
|
|
|
|
mode= BEZT_OK_VALUERANGE;
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
else
|
2009-01-27 11:09:30 +00:00
|
|
|
mode= BEZT_OK_REGION;
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* apply borderselect action */
|
2009-01-27 11:09:30 +00:00
|
|
|
borderselect_graphkeys(&ac, rect, mode, selectmode);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
2009-07-10 10:48:25 +00:00
|
|
|
/* send notifier that keyframe selection has changed */
|
|
|
|
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
|
|
|
|
2009-01-26 23:18:27 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2009-06-22 04:23:06 +00:00
|
|
|
void GRAPH_OT_select_border(wmOperatorType *ot)
|
2009-01-26 23:18:27 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Border Select";
|
2009-06-22 04:23:06 +00:00
|
|
|
ot->idname= "GRAPH_OT_select_border";
|
2009-07-11 10:20:48 +00:00
|
|
|
ot->description= "Select all keyframes within the specified region.";
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_border_select_invoke;
|
|
|
|
ot->exec= graphkeys_borderselect_exec;
|
|
|
|
ot->modal= WM_border_select_modal;
|
|
|
|
|
2009-07-02 01:01:18 +00:00
|
|
|
ot->poll= graphop_visible_keyframes_poll;
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
|
|
|
|
|
|
|
|
/* rna */
|
2009-11-06 22:51:08 +00:00
|
|
|
WM_operator_properties_gesture_border(ot, FALSE);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************** Column Select Operator **************************** */
|
|
|
|
/* This operator works in one of four ways:
|
|
|
|
* - 1) select all keyframes in the same frame as a selected one (KKEY)
|
|
|
|
* - 2) select all keyframes in the same frame as the current frame marker (CTRL-KKEY)
|
|
|
|
* - 3) select all keyframes in the same frame as a selected markers (SHIFT-KKEY)
|
|
|
|
* - 4) select all keyframes that occur between selected markers (ALT-KKEY)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* defines for column-select mode */
|
2009-01-27 05:04:23 +00:00
|
|
|
static EnumPropertyItem prop_column_select_types[] = {
|
2009-06-16 00:52:21 +00:00
|
|
|
{GRAPHKEYS_COLUMNSEL_KEYS, "KEYS", 0, "On Selected Keyframes", ""},
|
|
|
|
{GRAPHKEYS_COLUMNSEL_CFRA, "CFRA", 0, "On Current Frame", ""},
|
|
|
|
{GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN, "MARKERS_COLUMN", 0, "On Selected Markers", ""},
|
|
|
|
{GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN, "MARKERS_BETWEEN", 0, "Between Min/Max Selected Markers", ""},
|
|
|
|
{0, NULL, 0, NULL, NULL}
|
2009-01-26 23:18:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* ------------------- */
|
|
|
|
|
|
|
|
/* Selects all visible keyframes between the specified markers */
|
|
|
|
static void markers_selectkeys_between (bAnimContext *ac)
|
|
|
|
{
|
|
|
|
ListBase anim_data = {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
|
|
|
int filter;
|
|
|
|
|
2009-05-09 02:37:12 +00:00
|
|
|
BeztEditFunc ok_cb, select_cb;
|
2009-01-26 23:18:27 +00:00
|
|
|
BeztEditData bed;
|
|
|
|
float min, max;
|
|
|
|
|
|
|
|
/* get extreme markers */
|
2009-05-09 02:37:12 +00:00
|
|
|
ED_markers_get_minmax(ac->markers, 1, &min, &max);
|
2009-01-26 23:18:27 +00:00
|
|
|
min -= 0.5f;
|
|
|
|
max += 0.5f;
|
|
|
|
|
|
|
|
/* get editing funcs + data */
|
2009-05-09 02:37:12 +00:00
|
|
|
ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
|
2009-01-26 23:18:27 +00:00
|
|
|
select_cb= ANIM_editkeyframes_select(SELECT_ADD);
|
2009-05-09 02:37:12 +00:00
|
|
|
|
2009-01-26 23:18:27 +00:00
|
|
|
memset(&bed, 0, sizeof(BeztEditData));
|
|
|
|
bed.f1= min;
|
|
|
|
bed.f2= max;
|
|
|
|
|
|
|
|
/* filter data */
|
2009-01-27 05:04:23 +00:00
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
2009-01-26 23:18:27 +00:00
|
|
|
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
|
|
|
|
|
|
|
/* select keys in-between */
|
|
|
|
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
|
|
|
|
2009-06-23 13:25:31 +00:00
|
|
|
if (adt) {
|
|
|
|
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
2009-05-09 02:37:12 +00:00
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
2009-06-23 13:25:31 +00:00
|
|
|
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-05-09 02:37:12 +00:00
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
BLI_freelistN(&anim_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Selects all visible keyframes in the same frames as the specified elements */
|
|
|
|
static void columnselect_graph_keys (bAnimContext *ac, short mode)
|
|
|
|
{
|
|
|
|
ListBase anim_data= {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
|
|
|
int filter;
|
|
|
|
|
|
|
|
Scene *scene= ac->scene;
|
|
|
|
CfraElem *ce;
|
|
|
|
BeztEditFunc select_cb, ok_cb;
|
|
|
|
BeztEditData bed;
|
|
|
|
|
|
|
|
/* initialise keyframe editing data */
|
|
|
|
memset(&bed, 0, sizeof(BeztEditData));
|
|
|
|
|
|
|
|
/* build list of columns */
|
|
|
|
switch (mode) {
|
2009-01-27 05:04:23 +00:00
|
|
|
case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
|
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
|
|
|
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
|
|
|
|
|
|
|
for (ale= anim_data.first; ale; ale= ale->next)
|
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_to_cfraelem, NULL);
|
|
|
|
|
2009-01-26 23:18:27 +00:00
|
|
|
BLI_freelistN(&anim_data);
|
|
|
|
break;
|
|
|
|
|
2009-01-27 05:04:23 +00:00
|
|
|
case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
|
2009-01-26 23:18:27 +00:00
|
|
|
/* make a single CfraElem for storing this */
|
|
|
|
ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
|
|
|
|
BLI_addtail(&bed.list, ce);
|
|
|
|
|
|
|
|
ce->cfra= (float)CFRA;
|
|
|
|
break;
|
|
|
|
|
2009-01-27 05:04:23 +00:00
|
|
|
case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
|
2009-05-09 09:18:54 +00:00
|
|
|
ED_markers_make_cfra_list(ac->markers, &bed.list, 1);
|
2009-01-26 23:18:27 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* invalid option */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set up BezTriple edit callbacks */
|
|
|
|
select_cb= ANIM_editkeyframes_select(SELECT_ADD);
|
|
|
|
ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
|
|
|
|
|
|
|
|
/* loop through all of the keys and select additional keyframes
|
|
|
|
* based on the keys found to be selected above
|
|
|
|
*/
|
2009-01-27 05:04:23 +00:00
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
2009-01-26 23:18:27 +00:00
|
|
|
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
/* loop over cfraelems (stored in the BeztEditData->list)
|
|
|
|
* - we need to do this here, as we can apply fewer NLA-mapping conversions
|
|
|
|
*/
|
|
|
|
for (ce= bed.list.first; ce; ce= ce->next) {
|
|
|
|
/* set frame for validation callback to refer to */
|
2009-06-23 13:25:31 +00:00
|
|
|
if (ale)
|
2009-06-28 07:32:00 +00:00
|
|
|
bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
|
2009-01-26 23:18:27 +00:00
|
|
|
else
|
|
|
|
bed.f1= ce->cfra;
|
|
|
|
|
|
|
|
/* select elements with frame number matching cfraelem */
|
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free elements */
|
|
|
|
BLI_freelistN(&bed.list);
|
|
|
|
BLI_freelistN(&anim_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------- */
|
|
|
|
|
|
|
|
static int graphkeys_columnselect_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
bAnimContext ac;
|
|
|
|
short mode;
|
|
|
|
|
|
|
|
/* get editor data */
|
|
|
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
|
|
|
/* action to take depends on the mode */
|
|
|
|
mode= RNA_enum_get(op->ptr, "mode");
|
|
|
|
|
2009-01-27 05:04:23 +00:00
|
|
|
if (mode == GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN)
|
2009-01-26 23:18:27 +00:00
|
|
|
markers_selectkeys_between(&ac);
|
|
|
|
else
|
|
|
|
columnselect_graph_keys(&ac, mode);
|
|
|
|
|
2009-07-10 10:48:25 +00:00
|
|
|
/* set notifier that keyframe selection has changed */
|
|
|
|
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2009-06-22 04:23:06 +00:00
|
|
|
void GRAPH_OT_select_column (wmOperatorType *ot)
|
2009-01-26 23:18:27 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Select All";
|
2009-06-22 04:23:06 +00:00
|
|
|
ot->idname= "GRAPH_OT_select_column";
|
2009-07-11 10:20:48 +00:00
|
|
|
ot->description= "Select all keyframes on the specified frame(s).";
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= graphkeys_columnselect_exec;
|
2009-07-02 01:01:18 +00:00
|
|
|
ot->poll= graphop_visible_keyframes_poll;
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
|
|
|
|
|
|
|
|
/* props */
|
|
|
|
RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************** Mouse-Click Select Operator *********************** */
|
|
|
|
/* This operator works in one of three ways:
|
|
|
|
* - 1) keyframe under mouse - no special modifiers
|
|
|
|
* - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
|
|
|
|
* - 3) column select all keyframes in frame under mouse - CTRL modifier
|
|
|
|
*
|
|
|
|
* In addition to these basic options, the SHIFT modifier can be used to toggle the
|
|
|
|
* selection mode between replacing the selection (without) and inverting the selection (with).
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* defines for left-right select tool */
|
2009-04-12 08:17:46 +00:00
|
|
|
static EnumPropertyItem prop_graphkeys_leftright_select_types[] = {
|
2009-06-16 00:52:21 +00:00
|
|
|
{GRAPHKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
|
|
|
|
{GRAPHKEYS_LRSEL_NONE, "OFF", 0, "Don't select", ""},
|
|
|
|
{GRAPHKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
|
|
|
|
{GRAPHKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
|
|
|
|
{0, NULL, 0, NULL, NULL}
|
2009-01-26 23:18:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* ------------------- */
|
2009-01-27 05:04:23 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
NEAREST_HANDLE_LEFT = 0,
|
|
|
|
NEAREST_HANDLE_KEY,
|
|
|
|
NEAREST_HANDLE_RIGHT
|
|
|
|
} eHandleIndex;
|
|
|
|
|
|
|
|
/* Find the vertex (either handle (0/2) or the keyframe (1)) that is nearest to the mouse cursor (in area coordinates)
|
|
|
|
* Selected verts get a disadvantage, to make it easier to select handles behind.
|
|
|
|
* Returns eHandleIndex
|
|
|
|
*/
|
|
|
|
static short findnearest_fcurve_vert (bAnimContext *ac, int mval[2], FCurve **fcurve, BezTriple **bezt)
|
|
|
|
{
|
|
|
|
ListBase anim_data = {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
|
|
|
int filter;
|
|
|
|
|
|
|
|
SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
|
|
|
|
View2D *v2d= &ac->ar->v2d;
|
|
|
|
int hpoint=0, sco[3][2];
|
|
|
|
int dist= 100, temp, i;
|
|
|
|
|
|
|
|
/* clear pointers first */
|
|
|
|
*fcurve= 0;
|
|
|
|
*bezt= 0;
|
|
|
|
|
2009-07-28 06:50:30 +00:00
|
|
|
/* get curves to search through
|
|
|
|
* - if the option to only show keyframes that belong to selected F-Curves is enabled,
|
|
|
|
* include the 'only selected' flag...
|
|
|
|
*/
|
2009-01-27 05:04:23 +00:00
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
2009-07-28 06:50:30 +00:00
|
|
|
if (sipo->flag & SIPO_SELCUVERTSONLY)
|
|
|
|
filter |= ANIMFILTER_SEL;
|
2009-01-27 05:04:23 +00:00
|
|
|
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
|
|
|
|
|
|
|
for (ale= anim_data.first; ale; ale= ale->next) {
|
|
|
|
FCurve *fcu= (FCurve *)ale->key_data;
|
2009-06-23 13:25:31 +00:00
|
|
|
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
|
2009-01-27 05:04:23 +00:00
|
|
|
|
|
|
|
/* try to progressively get closer to the right point... */
|
|
|
|
if (fcu->bezt) {
|
|
|
|
BezTriple *bezt1=fcu->bezt, *prevbezt=NULL;
|
|
|
|
|
2009-06-23 13:25:31 +00:00
|
|
|
/* apply NLA mapping to all the keyframes */
|
|
|
|
if (adt)
|
|
|
|
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
|
|
|
|
2009-01-27 05:04:23 +00:00
|
|
|
for (i=0; i < fcu->totvert; i++, prevbezt=bezt1, bezt1++) {
|
|
|
|
/* convert beztriple points to screen-space */
|
|
|
|
UI_view2d_to_region_no_clip(v2d, bezt1->vec[0][0], bezt1->vec[0][1], &sco[0][0], &sco[0][1]);
|
|
|
|
UI_view2d_to_region_no_clip(v2d, bezt1->vec[1][0], bezt1->vec[1][1], &sco[1][0], &sco[1][1]);
|
|
|
|
UI_view2d_to_region_no_clip(v2d, bezt1->vec[2][0], bezt1->vec[2][1], &sco[2][0], &sco[2][1]);
|
|
|
|
|
|
|
|
/* keyframe - do select? */
|
|
|
|
temp= abs(mval[0] - sco[1][0]) + abs(mval[1] - sco[1][1]);
|
|
|
|
|
|
|
|
if (bezt1->f2 & SELECT)
|
|
|
|
temp += 5;
|
|
|
|
|
|
|
|
if (temp < dist) {
|
|
|
|
hpoint= NEAREST_HANDLE_KEY;
|
|
|
|
*bezt= bezt1;
|
|
|
|
dist= temp;
|
|
|
|
*fcurve= fcu;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* handles - only do them if they're visible */
|
2009-03-18 10:58:18 +00:00
|
|
|
// XXX also need to check for int-values only?
|
2009-01-27 05:04:23 +00:00
|
|
|
if ((sipo->flag & SIPO_NOHANDLES)==0) {
|
|
|
|
/* first handle only visible if previous segment had handles */
|
|
|
|
if ( (!prevbezt && (bezt1->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) )
|
|
|
|
{
|
|
|
|
temp= -3 + abs(mval[0] - sco[0][0]) + abs(mval[1] - sco[0][1]);
|
|
|
|
if (bezt1->f1 & SELECT)
|
|
|
|
temp += 5;
|
|
|
|
|
|
|
|
if (temp < dist) {
|
|
|
|
hpoint= NEAREST_HANDLE_LEFT;
|
|
|
|
*bezt= bezt1;
|
|
|
|
dist= temp;
|
|
|
|
*fcurve= fcu;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* second handle only visible if this segment is bezier */
|
|
|
|
if (bezt1->ipo == BEZT_IPO_BEZ)
|
|
|
|
{
|
|
|
|
temp= abs(mval[0] - sco[2][0]) + abs(mval[1] - sco[2][1]);
|
|
|
|
if (bezt1->f3 & SELECT)
|
|
|
|
temp += 5;
|
|
|
|
|
|
|
|
if (temp < dist) {
|
|
|
|
hpoint= NEAREST_HANDLE_RIGHT;
|
|
|
|
*bezt=bezt1;
|
|
|
|
dist= temp;
|
|
|
|
*fcurve= fcu;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-23 13:25:31 +00:00
|
|
|
|
|
|
|
/* un-apply NLA mapping from all the keyframes */
|
|
|
|
if (adt)
|
|
|
|
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
2009-01-27 05:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free channels */
|
|
|
|
BLI_freelistN(&anim_data);
|
|
|
|
|
|
|
|
/* return handle */
|
|
|
|
return hpoint;
|
|
|
|
}
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* option 1) select keyframe directly under mouse */
|
2009-04-12 08:17:46 +00:00
|
|
|
static void mouse_graph_keys (bAnimContext *ac, int mval[], short select_mode, short curves_only)
|
2009-01-26 23:18:27 +00:00
|
|
|
{
|
2009-01-27 05:04:23 +00:00
|
|
|
FCurve *fcu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
short handle;
|
2009-02-22 05:34:47 +00:00
|
|
|
int filter;
|
2009-01-27 05:04:23 +00:00
|
|
|
|
|
|
|
/* find the beztriple that we're selecting, and the handle that was clicked on */
|
|
|
|
handle= findnearest_fcurve_vert(ac, mval, &fcu, &bezt);
|
|
|
|
|
|
|
|
/* check if anything to select */
|
|
|
|
if (fcu == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* deselect all other curves? */
|
2009-04-12 08:17:46 +00:00
|
|
|
if (select_mode == SELECT_REPLACE) {
|
|
|
|
/* reset selection mode */
|
|
|
|
select_mode= SELECT_ADD;
|
|
|
|
|
|
|
|
/* deselect all other channels and keyframes */
|
2009-04-12 13:19:21 +00:00
|
|
|
//ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
|
2009-04-12 08:17:46 +00:00
|
|
|
deselect_graph_keys(ac, 0, SELECT_SUBTRACT);
|
2009-01-27 05:04:23 +00:00
|
|
|
}
|
|
|
|
|
2009-04-12 08:17:46 +00:00
|
|
|
/* if points can be selected on this F-Curve */
|
|
|
|
// TODO: what about those with no keyframes?
|
|
|
|
if ((curves_only == 0) && ((fcu->flag & FCURVE_PROTECTED)==0)) {
|
2009-01-27 05:04:23 +00:00
|
|
|
/* only if there's keyframe */
|
|
|
|
if (bezt) {
|
|
|
|
/* depends on selection mode */
|
2009-04-12 08:17:46 +00:00
|
|
|
if (select_mode == SELECT_INVERT) {
|
2009-01-27 05:04:23 +00:00
|
|
|
/* keyframe - invert select of all */
|
|
|
|
if (handle == NEAREST_HANDLE_KEY) {
|
|
|
|
if (BEZSELECTED(bezt)) {
|
|
|
|
BEZ_DESEL(bezt);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BEZ_SEL(bezt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* handles - toggle selection of relevant handle */
|
|
|
|
else if (handle == NEAREST_HANDLE_LEFT) {
|
|
|
|
/* toggle selection */
|
|
|
|
bezt->f1 ^= SELECT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* toggle selection */
|
|
|
|
bezt->f3 ^= SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* if the keyframe was clicked on, select all verts of given beztriple */
|
|
|
|
if (handle == NEAREST_HANDLE_KEY) {
|
|
|
|
BEZ_SEL(bezt);
|
|
|
|
}
|
|
|
|
/* otherwise, select the handle that applied */
|
|
|
|
else if (handle == NEAREST_HANDLE_LEFT)
|
|
|
|
bezt->f1 |= SELECT;
|
|
|
|
else
|
|
|
|
bezt->f3 |= SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-04-12 08:17:46 +00:00
|
|
|
else {
|
|
|
|
BeztEditFunc select_cb;
|
|
|
|
BeztEditData bed;
|
2009-07-28 06:50:30 +00:00
|
|
|
|
2009-04-12 08:17:46 +00:00
|
|
|
/* initialise keyframe editing data */
|
|
|
|
memset(&bed, 0, sizeof(BeztEditData));
|
|
|
|
|
|
|
|
/* set up BezTriple edit callbacks */
|
|
|
|
select_cb= ANIM_editkeyframes_select(select_mode);
|
|
|
|
|
|
|
|
/* select all keyframes */
|
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, fcu, NULL, select_cb, NULL);
|
|
|
|
}
|
2009-02-09 10:33:05 +00:00
|
|
|
|
|
|
|
/* select or deselect curve? */
|
2009-04-12 08:17:46 +00:00
|
|
|
if (select_mode == SELECT_INVERT)
|
2009-02-09 10:33:05 +00:00
|
|
|
fcu->flag ^= FCURVE_SELECTED;
|
2009-04-12 08:17:46 +00:00
|
|
|
else if (select_mode == SELECT_ADD)
|
2009-02-22 05:34:47 +00:00
|
|
|
fcu->flag |= FCURVE_SELECTED;
|
2009-02-09 10:33:05 +00:00
|
|
|
|
2009-02-22 05:34:47 +00:00
|
|
|
/* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
|
|
|
|
if (fcu->flag & FCURVE_SELECTED) {
|
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
NLA SoC: Operators for 'tweaking' strip actions (TAB-Key for both)
In this commit, I've introduced the mechanism by which actions already referenced by strips used in the NLA can be edited (or 'tweaked'). To use, simply select a strip you wish to edit, and hit that TAB key to start tweaking that strip's action, and hit TAB again once you're done.
What happens when you enter 'tweak mode':
1) The action of the active strip temporarily becomes the 'active action' of the AnimData block. You are now able to edit this in one of the Animation Editors (DopeSheet/Action, Graph Editors) as per normal (i.e. sliding keyframes around, inserting keyframes, etc.). The 'action-line' will therefore get drawn immediately above the active track containing the active strip, so that it's clear that that's what we're editing.
2) All the NLA-tracks (and all the strips within them) that occur after the track that the active strip lived in get disabled while you're in tweakmode. This is equivalent to travelling back to an earlier state in a construction history stack.
3) The active NLA track also gets disabled while in tweakmode, since it would otherwise interfere with the correct functioning of the tweaking for the action of interest.
4) The 'real' active action (i.e. the one displaced by the active strip's action) gets put into temp storage, and will be restored after you exit tweakmode.
5) Any strips which also reference the action being tweaked will get highlighted in red shading to indicate that you may be making some changes to the action which you don't really want to make for the other users too.
Please note though, that this is only a rough prototype of this functionality, with some niceties still to come. i.e.:
* NLA-tracks after the active track should still get drawn above the 'tweaking action line', but perhaps with different appearance?
* Various tools will still need awareness of this to prevent corrupting operations from taking place. How to proceed is still undecided...
* When exiting tweak-mode, the strip the action came from still needs some form of syncing with the modified action... there are a few tricky issues here that will need to be solved
* Evaluation code doesn't totally take this into account yet...
---
Also, fixed a number of bugs with various code (notably selection, and also a few drawing bugs)
2009-06-05 05:18:07 +00:00
|
|
|
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
|
2009-02-09 10:33:05 +00:00
|
|
|
}
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Option 2) Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
|
2009-04-12 08:17:46 +00:00
|
|
|
static void graphkeys_mselect_leftright (bAnimContext *ac, short leftright, short select_mode)
|
2009-01-26 23:18:27 +00:00
|
|
|
{
|
|
|
|
ListBase anim_data = {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
|
|
|
int filter;
|
|
|
|
|
|
|
|
BeztEditFunc ok_cb, select_cb;
|
|
|
|
BeztEditData bed;
|
|
|
|
Scene *scene= ac->scene;
|
|
|
|
|
2009-04-12 08:17:46 +00:00
|
|
|
/* if select mode is replace, deselect all keyframes (and channels) first */
|
2009-01-26 23:18:27 +00:00
|
|
|
if (select_mode==SELECT_REPLACE) {
|
2009-04-12 08:17:46 +00:00
|
|
|
/* reset selection mode to add to selection */
|
|
|
|
select_mode= SELECT_ADD;
|
|
|
|
|
|
|
|
/* deselect all other channels and keyframes */
|
|
|
|
ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
|
2009-01-26 23:18:27 +00:00
|
|
|
deselect_graph_keys(ac, 0, SELECT_SUBTRACT);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set callbacks and editing data */
|
|
|
|
ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
|
|
|
|
select_cb= ANIM_editkeyframes_select(select_mode);
|
|
|
|
|
|
|
|
memset(&bed, 0, sizeof(BeztEditFunc));
|
2009-01-27 05:04:23 +00:00
|
|
|
if (leftright == GRAPHKEYS_LRSEL_LEFT) {
|
2009-07-07 06:56:29 +00:00
|
|
|
bed.f1 = MINAFRAMEF;
|
2009-01-26 23:18:27 +00:00
|
|
|
bed.f2 = (float)(CFRA + 0.1f);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bed.f1 = (float)(CFRA - 0.1f);
|
|
|
|
bed.f2 = MAXFRAMEF;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* filter data */
|
2009-01-27 05:04:23 +00:00
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
2009-01-26 23:18:27 +00:00
|
|
|
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
|
|
|
|
|
|
|
/* select keys on the side where most data occurs */
|
|
|
|
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
|
|
|
|
2009-06-23 13:25:31 +00:00
|
|
|
if (adt) {
|
|
|
|
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
|
2009-01-26 23:18:27 +00:00
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
2009-06-23 13:25:31 +00:00
|
|
|
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
BLI_freelistN(&anim_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
|
2009-04-12 08:17:46 +00:00
|
|
|
static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short select_mode)
|
2009-01-26 23:18:27 +00:00
|
|
|
{
|
|
|
|
ListBase anim_data= {NULL, NULL};
|
|
|
|
bAnimListElem *ale;
|
|
|
|
int filter;
|
|
|
|
|
|
|
|
BeztEditFunc select_cb, ok_cb;
|
|
|
|
BeztEditData bed;
|
2009-04-12 08:17:46 +00:00
|
|
|
FCurve *fcu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
float selx = (float)ac->scene->r.cfra;
|
|
|
|
|
|
|
|
/* find the beztriple that occurs on this frame, and use his as the frame number we're using */
|
|
|
|
findnearest_fcurve_vert(ac, mval, &fcu, &bezt);
|
|
|
|
|
|
|
|
/* check if anything to select */
|
|
|
|
if (ELEM(NULL, fcu, bezt))
|
|
|
|
return;
|
|
|
|
selx= bezt->vec[1][0];
|
|
|
|
|
|
|
|
/* if select mode is replace, deselect all keyframes (and channels) first */
|
|
|
|
if (select_mode==SELECT_REPLACE) {
|
|
|
|
/* reset selection mode to add to selection */
|
|
|
|
select_mode= SELECT_ADD;
|
|
|
|
|
|
|
|
/* deselect all other channels and keyframes */
|
|
|
|
ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
|
|
|
|
deselect_graph_keys(ac, 0, SELECT_SUBTRACT);
|
|
|
|
}
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* initialise keyframe editing data */
|
|
|
|
memset(&bed, 0, sizeof(BeztEditData));
|
|
|
|
|
|
|
|
/* set up BezTriple edit callbacks */
|
2009-04-12 08:17:46 +00:00
|
|
|
select_cb= ANIM_editkeyframes_select(select_mode);
|
2009-01-26 23:18:27 +00:00
|
|
|
ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
|
|
|
|
|
|
|
|
/* loop through all of the keys and select additional keyframes
|
|
|
|
* based on the keys found to be selected above
|
|
|
|
*/
|
2009-01-27 05:04:23 +00:00
|
|
|
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
2009-01-26 23:18:27 +00:00
|
|
|
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
/* set frame for validation callback to refer to */
|
2009-06-23 13:25:31 +00:00
|
|
|
if (adt)
|
2009-06-28 07:32:00 +00:00
|
|
|
bed.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
|
2009-01-26 23:18:27 +00:00
|
|
|
else
|
|
|
|
bed.f1= selx;
|
|
|
|
|
2009-01-27 05:04:23 +00:00
|
|
|
/* select elements with frame number matching cfra */
|
2009-01-26 23:18:27 +00:00
|
|
|
ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free elements */
|
|
|
|
BLI_freelistN(&bed.list);
|
|
|
|
BLI_freelistN(&anim_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------- */
|
|
|
|
|
|
|
|
/* handle clicking */
|
|
|
|
static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
{
|
|
|
|
bAnimContext ac;
|
|
|
|
Scene *scene;
|
|
|
|
ARegion *ar;
|
|
|
|
View2D *v2d;
|
|
|
|
short selectmode;
|
|
|
|
int mval[2];
|
|
|
|
|
|
|
|
/* get editor data */
|
|
|
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
|
|
|
return OPERATOR_CANCELLED;
|
2009-01-27 05:04:23 +00:00
|
|
|
|
2009-01-26 23:18:27 +00:00
|
|
|
/* get useful pointers from animation context data */
|
|
|
|
scene= ac.scene;
|
|
|
|
ar= ac.ar;
|
|
|
|
v2d= &ar->v2d;
|
|
|
|
|
|
|
|
/* get mouse coordinates (in region coordinates) */
|
|
|
|
mval[0]= (event->x - ar->winrct.xmin);
|
|
|
|
mval[1]= (event->y - ar->winrct.ymin);
|
|
|
|
|
|
|
|
/* select mode is either replace (deselect all, then add) or add/extend */
|
2009-03-29 02:15:13 +00:00
|
|
|
if (RNA_boolean_get(op->ptr, "extend"))
|
2009-01-26 23:18:27 +00:00
|
|
|
selectmode= SELECT_INVERT;
|
|
|
|
else
|
|
|
|
selectmode= SELECT_REPLACE;
|
|
|
|
|
|
|
|
/* figure out action to take */
|
|
|
|
if (RNA_enum_get(op->ptr, "left_right")) {
|
|
|
|
/* select all keys on same side of current frame as mouse */
|
|
|
|
float x;
|
|
|
|
|
|
|
|
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
|
|
|
|
if (x < CFRA)
|
2009-01-27 05:04:23 +00:00
|
|
|
RNA_int_set(op->ptr, "left_right", GRAPHKEYS_LRSEL_LEFT);
|
2009-01-26 23:18:27 +00:00
|
|
|
else
|
2009-01-27 05:04:23 +00:00
|
|
|
RNA_int_set(op->ptr, "left_right", GRAPHKEYS_LRSEL_RIGHT);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
2009-04-12 08:17:46 +00:00
|
|
|
graphkeys_mselect_leftright(&ac, RNA_enum_get(op->ptr, "left_right"), selectmode);
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
2009-03-29 02:15:13 +00:00
|
|
|
else if (RNA_boolean_get(op->ptr, "column")) {
|
2009-04-12 08:17:46 +00:00
|
|
|
/* select all keyframes in the same frame as the one that was under the mouse */
|
|
|
|
graphkeys_mselect_column(&ac, mval, selectmode);
|
|
|
|
}
|
|
|
|
else if (RNA_boolean_get(op->ptr, "curves")) {
|
|
|
|
/* select all keyframes in F-Curve under mouse */
|
|
|
|
mouse_graph_keys(&ac, mval, selectmode, 1);
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* select keyframe under mouse */
|
2009-04-12 08:17:46 +00:00
|
|
|
mouse_graph_keys(&ac, mval, selectmode, 0);
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
|
2009-07-10 10:48:25 +00:00
|
|
|
/* set notifier that keyframe selection (and also channel selection in some cases) has changed */
|
|
|
|
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT|ND_ANIMCHAN_SELECT, NULL);
|
2009-01-26 23:18:27 +00:00
|
|
|
|
2009-01-28 15:39:39 +00:00
|
|
|
/* for tweak grab to work */
|
2009-01-28 21:43:43 +00:00
|
|
|
return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
|
2009-06-22 04:23:06 +00:00
|
|
|
void GRAPH_OT_clickselect (wmOperatorType *ot)
|
2009-01-26 23:18:27 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Mouse Select Keys";
|
2009-06-22 04:23:06 +00:00
|
|
|
ot->idname= "GRAPH_OT_clickselect";
|
2009-07-11 10:20:48 +00:00
|
|
|
ot->description= "Select keyframes by clicking on them.";
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= graphkeys_clickselect_invoke;
|
2009-07-02 01:01:18 +00:00
|
|
|
ot->poll= graphop_visible_keyframes_poll;
|
2009-01-26 23:18:27 +00:00
|
|
|
|
|
|
|
/* id-props */
|
|
|
|
// XXX should we make this into separate operators?
|
2009-04-12 08:17:46 +00:00
|
|
|
RNA_def_enum(ot->srna, "left_right", prop_graphkeys_leftright_select_types, 0, "Left Right", ""); // CTRLKEY
|
2009-03-29 02:15:13 +00:00
|
|
|
RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
|
2009-04-12 08:17:46 +00:00
|
|
|
RNA_def_boolean(ot->srna, "column", 0, "Column Select", "Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY
|
|
|
|
RNA_def_boolean(ot->srna, "curves", 0, "Only Curves", "Select all the keyframes in the curve"); // CTRLKEY + ALTKEY
|
2009-01-26 23:18:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************** */
|