76
76
/* Deselects keyframes in the Graph Editor
77
77
* - This is called by the deselect all operator, as well as other ones!
79
* - test: check if select or deselect all
79
* - test: check if select or deselect all
80
80
* - sel: how to select keyframes
84
84
* - do_channels: whether to affect selection status of channels
86
static void deselect_graph_keys (bAnimContext *ac, short test, short sel, short do_channels)
86
static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short do_channels)
88
88
ListBase anim_data = {NULL, NULL};
89
89
bAnimListElem *ale;
92
SpaceIpo *sipo= (SpaceIpo *)ac->sl;
93
KeyframeEditData ked= {{NULL}};
92
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
93
KeyframeEditData ked = {{NULL}};
94
94
KeyframeEditFunc test_cb, sel_cb;
96
96
/* determine type-based settings */
97
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
97
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
100
100
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
102
102
/* init BezTriple looping data */
103
test_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
103
test_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
105
105
/* See if we should be selecting or deselecting */
107
for (ale= anim_data.first; ale; ale= ale->next) {
107
for (ale = anim_data.first; ale; ale = ale->next) {
108
108
if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
109
sel= SELECT_SUBTRACT;
109
sel = SELECT_SUBTRACT;
115
115
/* convert sel to selectmode, and use that to get editor */
116
sel_cb= ANIM_editkeyframes_select(sel);
116
sel_cb = ANIM_editkeyframes_select(sel);
118
118
/* Now set the flags */
119
for (ale= anim_data.first; ale; ale= ale->next) {
120
FCurve *fcu= (FCurve *)ale->key_data;
119
for (ale = anim_data.first; ale; ale = ale->next) {
120
FCurve *fcu = (FCurve *)ale->key_data;
122
122
/* Keyframes First */
123
123
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
161
161
deselect_graph_keys(&ac, 1, SELECT_ADD, TRUE);
163
163
/* set notifier that things have changed */
164
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
164
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
166
166
return OPERATOR_FINISHED;
169
void GRAPH_OT_select_all_toggle (wmOperatorType *ot)
169
void GRAPH_OT_select_all_toggle(wmOperatorType *ot)
171
171
/* identifiers */
172
172
ot->name = "Select All";
178
178
ot->poll = graphop_visible_keyframes_poll;
181
ot->flag = OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
181
ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
184
184
ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
187
187
/* ******************** Border Select Operator **************************** */
188
188
/* This operator currently works in one of three ways:
189
* -> BKEY - 1) all keyframes within region are selected (validation with BEZT_OK_REGION)
189
* -> BKEY - 1) all keyframes within region are selected (validation with BEZT_OK_REGION)
190
190
* -> ALT-BKEY - depending on which axis of the region was larger...
191
191
* -> 2) x-axis, so select all frames within frame range (validation with BEZT_OK_FRAMERANGE)
192
192
* -> 3) y-axis, so select all frames within channels that region included (validation with BEZT_OK_VALUERANGE)
197
197
* this, and allow handles to be considered independently too.
198
198
* Also, for convenience, handles should get same status as keyframe (if it was within bounds).
200
static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, short selectmode, short incl_handles)
200
static void borderselect_graphkeys(bAnimContext *ac, rcti rect, short mode, short selectmode, short incl_handles)
202
202
ListBase anim_data = {NULL, NULL};
203
203
bAnimListElem *ale;
204
204
int filter, mapping_flag;
206
SpaceIpo *sipo= (SpaceIpo *)ac->sl;
206
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
207
207
KeyframeEditData ked;
208
208
KeyframeEditFunc ok_cb, select_cb;
209
View2D *v2d= &ac->ar->v2d;
209
View2D *v2d = &ac->ar->v2d;
212
212
/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
214
214
UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
216
216
/* filter data */
217
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
217
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
218
218
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
220
220
/* get beztriple editing/validation funcs */
221
select_cb= ANIM_editkeyframes_select(selectmode);
222
ok_cb= ANIM_editkeyframes_ok(mode);
221
select_cb = ANIM_editkeyframes_select(selectmode);
222
ok_cb = ANIM_editkeyframes_ok(mode);
224
224
/* init editing data */
225
225
memset(&ked, 0, sizeof(KeyframeEditData));
228
228
/* treat handles separately? */
229
229
if (incl_handles) {
230
230
ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES;
234
mapping_flag= ANIM_UNITCONV_ONLYKEYS;
234
mapping_flag = ANIM_UNITCONV_ONLYKEYS;
236
236
/* loop over data, doing border select */
237
for (ale= anim_data.first; ale; ale= ale->next) {
238
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
239
FCurve *fcu= (FCurve *)ale->key_data;
237
for (ale = anim_data.first; ale; ale = ale->next) {
238
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
239
FCurve *fcu = (FCurve *)ale->key_data;
241
241
/* apply unit corrections */
242
242
ANIM_unit_mapping_apply_fcurve(ac->scene, ale->id, ale->key_data, mapping_flag);
245
245
* guess when a callback might use something different
248
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles==0);
248
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0);
250
250
/* set horizontal range (if applicable)
251
251
* NOTE: these values are only used for x-range and y-range but not region
252
* (which uses ked.data, i.e. rectf)
252
* (which uses ked.data, i.e. rectf)
254
254
if (mode != BEZT_OK_VALUERANGE) {
263
263
/* firstly, check if any keyframes will be hit by this */
276
276
/* un-apply NLA mapping from all the keyframes */
278
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles==0);
278
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0);
280
280
/* unapply unit corrections */
281
ANIM_unit_mapping_apply_fcurve(ac->scene, ale->id, ale->key_data, ANIM_UNITCONV_RESTORE|mapping_flag);
281
ANIM_unit_mapping_apply_fcurve(ac->scene, ale->id, ale->key_data, ANIM_UNITCONV_RESTORE | mapping_flag);
300
300
return OPERATOR_CANCELLED;
302
302
/* clear all selection if not extending selection */
303
extend= RNA_boolean_get(op->ptr, "extend");
303
extend = RNA_boolean_get(op->ptr, "extend");
305
305
deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, TRUE);
308
308
* - 'gesture_mode' from the operator specifies how to select
309
309
* - 'include_handles' from the operator specifies whether to include handles in the selection
311
if (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT)
312
selectmode= SELECT_ADD;
311
if (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT)
312
selectmode = SELECT_ADD;
314
selectmode= SELECT_SUBTRACT;
314
selectmode = SELECT_SUBTRACT;
316
316
incl_handles = RNA_boolean_get(op->ptr, "include_handles");
318
318
/* get settings from operator */
319
rect.xmin = RNA_int_get(op->ptr, "xmin");
320
rect.ymin = RNA_int_get(op->ptr, "ymin");
321
rect.xmax = RNA_int_get(op->ptr, "xmax");
322
rect.ymax = RNA_int_get(op->ptr, "ymax");
319
WM_operator_properties_border_to_rcti(op, &rect);
324
321
/* selection 'mode' depends on whether borderselect region only matters on one axis */
325
322
if (RNA_boolean_get(op->ptr, "axis_range")) {
328
325
* - the frame-range select option is favored over the channel one (x over y), as frame-range one is often
329
326
* used for tweaking timing when "blocking", while channels is not that useful...
331
if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin))
332
mode= BEZT_OK_FRAMERANGE;
328
if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect)))
329
mode = BEZT_OK_FRAMERANGE;
334
mode= BEZT_OK_VALUERANGE;
331
mode = BEZT_OK_VALUERANGE;
337
mode= BEZT_OK_REGION;
334
mode = BEZT_OK_REGION;
339
336
/* apply borderselect action */
340
337
borderselect_graphkeys(&ac, rect, mode, selectmode, incl_handles);
342
339
/* send notifier that keyframe selection has changed */
343
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
340
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
345
342
return OPERATOR_FINISHED;
392
389
/* Selects all visible keyframes between the specified markers */
393
390
/* TODO, this is almost an _exact_ duplicate of a function of the same name in action_select.c
394
391
* should de-duplicate - campbell */
395
static void markers_selectkeys_between (bAnimContext *ac)
392
static void markers_selectkeys_between(bAnimContext *ac)
397
394
ListBase anim_data = {NULL, NULL};
398
395
bAnimListElem *ale;
401
398
KeyframeEditFunc ok_cb, select_cb;
402
KeyframeEditData ked= {{NULL}};
399
KeyframeEditData ked = {{NULL}};
405
402
/* get extreme markers */
410
407
/* get editing funcs + data */
411
ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
412
select_cb= ANIM_editkeyframes_select(SELECT_ADD);
408
ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
409
select_cb = ANIM_editkeyframes_select(SELECT_ADD);
417
414
/* filter data */
418
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
415
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
419
416
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
421
418
/* select keys in-between */
422
for (ale= anim_data.first; ale; ale= ale->next) {
423
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
419
for (ale = anim_data.first; ale; ale = ale->next) {
420
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
426
423
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
440
437
/* Selects all visible keyframes in the same frames as the specified elements */
441
static void columnselect_graph_keys (bAnimContext *ac, short mode)
438
static void columnselect_graph_keys(bAnimContext *ac, short mode)
443
ListBase anim_data= {NULL, NULL};
440
ListBase anim_data = {NULL, NULL};
444
441
bAnimListElem *ale;
447
Scene *scene= ac->scene;
444
Scene *scene = ac->scene;
449
446
KeyframeEditFunc select_cb, ok_cb;
450
447
KeyframeEditData ked;
455
452
/* build list of columns */
457
454
case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
458
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
455
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
459
456
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
461
for (ale= anim_data.first; ale; ale= ale->next)
458
for (ale = anim_data.first; ale; ale = ale->next)
462
459
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
464
461
BLI_freelistN(&anim_data);
467
464
case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
468
465
/* make a single CfraElem for storing this */
469
ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
466
ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
470
467
BLI_addtail(&ked.list, ce);
472
ce->cfra= (float)CFRA;
469
ce->cfra = (float)CFRA;
475
472
case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
483
480
/* set up BezTriple edit callbacks */
484
select_cb= ANIM_editkeyframes_select(SELECT_ADD);
485
ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
481
select_cb = ANIM_editkeyframes_select(SELECT_ADD);
482
ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
487
484
/* loop through all of the keys and select additional keyframes
488
485
* based on the keys found to be selected above
490
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
487
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
491
488
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
493
for (ale= anim_data.first; ale; ale= ale->next) {
494
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
490
for (ale = anim_data.first; ale; ale = ale->next) {
491
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
496
493
/* loop over cfraelems (stored in the KeyframeEditData->list)
497
494
* - we need to do this here, as we can apply fewer NLA-mapping conversions
499
for (ce= ked.list.first; ce; ce= ce->next) {
496
for (ce = ked.list.first; ce; ce = ce->next) {
500
497
/* set frame for validation callback to refer to */
501
ked.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
498
ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
503
500
/* select elements with frame number matching cfraelem */
504
501
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
522
519
return OPERATOR_CANCELLED;
524
521
/* action to take depends on the mode */
525
mode= RNA_enum_get(op->ptr, "mode");
522
mode = RNA_enum_get(op->ptr, "mode");
527
524
if (mode == GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN)
528
525
markers_selectkeys_between(&ac);
530
527
columnselect_graph_keys(&ac, mode);
532
529
/* set notifier that keyframe selection has changed */
533
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
530
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
535
532
return OPERATOR_FINISHED;
538
void GRAPH_OT_select_column (wmOperatorType *ot)
535
void GRAPH_OT_select_column(wmOperatorType *ot)
540
537
/* identifiers */
541
538
ot->name = "Select All";
547
544
ot->poll = graphop_visible_keyframes_poll;
550
ot->flag = OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
547
ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
553
550
ot->prop = RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
556
553
/* ******************** Select Linked Operator *********************** */
558
static int graphkeys_select_linked_exec (bContext *C, wmOperator *UNUSED(op))
555
static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
562
ListBase anim_data= {NULL, NULL};
559
ListBase anim_data = {NULL, NULL};
563
560
bAnimListElem *ale;
571
568
return OPERATOR_CANCELLED;
573
570
/* loop through all of the keys and select additional keyframes based on these */
574
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
571
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
575
572
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
577
for (ale= anim_data.first; ale; ale= ale->next) {
578
FCurve *fcu= (FCurve *)ale->key_data;
574
for (ale = anim_data.first; ale; ale = ale->next) {
575
FCurve *fcu = (FCurve *)ale->key_data;
580
577
/* check if anything selected? */
581
578
if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
588
585
BLI_freelistN(&anim_data);
590
587
/* set notifier that keyframe selection has changed */
591
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
588
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
593
590
return OPERATOR_FINISHED;
596
void GRAPH_OT_select_linked (wmOperatorType *ot)
593
void GRAPH_OT_select_linked(wmOperatorType *ot)
598
595
/* identifiers */
599
596
ot->name = "Select Linked";
605
602
ot->poll = graphop_visible_keyframes_poll;
608
ot->flag = OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
605
ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
611
608
/* ******************** Select More/Less Operators *********************** */
613
610
/* Common code to perform selection */
614
static void select_moreless_graph_keys (bAnimContext *ac, short mode)
611
static void select_moreless_graph_keys(bAnimContext *ac, short mode)
616
ListBase anim_data= {NULL, NULL};
613
ListBase anim_data = {NULL, NULL};
617
614
bAnimListElem *ale;
624
621
/* init selmap building data */
625
build_cb= ANIM_editkeyframes_buildselmap(mode);
622
build_cb = ANIM_editkeyframes_buildselmap(mode);
626
623
memset(&ked, 0, sizeof(KeyframeEditData));
628
625
/* loop through all of the keys and select additional keyframes based on these */
629
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
626
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
630
627
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
632
for (ale= anim_data.first; ale; ale= ale->next) {
633
FCurve *fcu= (FCurve *)ale->key_data;
629
for (ale = anim_data.first; ale; ale = ale->next) {
630
FCurve *fcu = (FCurve *)ale->key_data;
635
632
/* only continue if F-Curve has keyframes */
636
633
if (fcu->bezt == NULL)
639
636
/* build up map of whether F-Curve's keyframes should be selected or not */
640
ked.data= MEM_callocN(fcu->totvert, "selmap graphEdit");
637
ked.data = MEM_callocN(fcu->totvert, "selmap graphEdit");
641
638
ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
643
640
/* based on this map, adjust the selection status of the keyframes */
666
663
select_moreless_graph_keys(&ac, SELMAP_MORE);
668
665
/* set notifier that keyframe selection has changed */
669
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
666
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
671
668
return OPERATOR_FINISHED;
674
void GRAPH_OT_select_more (wmOperatorType *ot)
671
void GRAPH_OT_select_more(wmOperatorType *ot)
676
673
/* identifiers */
677
674
ot->name = "Select More";
683
680
ot->poll = graphop_visible_keyframes_poll;
686
ot->flag = OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
683
ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
689
686
/* ----------------- */
691
static int graphkeys_select_less_exec (bContext *C, wmOperator *UNUSED(op))
688
static int graphkeys_select_less_exec(bContext *C, wmOperator *UNUSED(op))
700
697
select_moreless_graph_keys(&ac, SELMAP_LESS);
702
699
/* set notifier that keyframe selection has changed */
703
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
700
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
705
702
return OPERATOR_FINISHED;
708
void GRAPH_OT_select_less (wmOperatorType *ot)
705
void GRAPH_OT_select_less(wmOperatorType *ot)
710
707
/* identifiers */
711
708
ot->name = "Select Less";
734
731
/* --------------------------------- */
736
static void graphkeys_select_leftright (bAnimContext *ac, short leftright, short select_mode)
733
static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
738
735
ListBase anim_data = {NULL, NULL};
739
736
bAnimListElem *ale;
742
739
KeyframeEditFunc ok_cb, select_cb;
743
KeyframeEditData ked= {{NULL}};
744
Scene *scene= ac->scene;
740
KeyframeEditData ked = {{NULL}};
741
Scene *scene = ac->scene;
746
743
/* if select mode is replace, deselect all keyframes (and channels) first */
747
if (select_mode==SELECT_REPLACE) {
748
select_mode= SELECT_ADD;
744
if (select_mode == SELECT_REPLACE) {
745
select_mode = SELECT_ADD;
750
747
/* - deselect all other keyframes, so that just the newly selected remain
751
748
* - channels aren't deselected, since we don't re-select any as a consequence
756
753
/* set callbacks and editing data */
757
ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
758
select_cb= ANIM_editkeyframes_select(select_mode);
754
ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
755
select_cb = ANIM_editkeyframes_select(select_mode);
760
757
if (leftright == GRAPHKEYS_LRSEL_LEFT) {
761
758
ked.f1 = MINAFRAMEF;
762
759
ked.f2 = (float)(CFRA + 0.1f);
765
762
ked.f1 = (float)(CFRA - 0.1f);
766
763
ked.f2 = MAXFRAMEF;
769
766
/* filter data */
770
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
767
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
771
768
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
773
770
/* select keys */
774
for (ale= anim_data.first; ale; ale= ale->next) {
775
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
771
for (ale = anim_data.first; ale; ale = ale->next) {
772
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
778
775
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
802
799
/* select mode is either replace (deselect all, then add) or add/extend */
803
800
if (RNA_boolean_get(op->ptr, "extend"))
804
selectmode= SELECT_INVERT;
801
selectmode = SELECT_INVERT;
806
selectmode= SELECT_REPLACE;
803
selectmode = SELECT_REPLACE;
808
805
/* if "test" mode is set, we don't have any info to set this with */
809
806
if (leftright == GRAPHKEYS_LRSEL_TEST)
813
810
graphkeys_select_leftright(&ac, leftright, selectmode);
815
812
/* set notifier that keyframe selection (and channels too) have changed */
816
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|ND_ANIMCHAN|NA_SELECTED, NULL);
813
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
818
815
return OPERATOR_FINISHED;
821
static int graphkeys_select_leftright_invoke (bContext *C, wmOperator *op, wmEvent *event)
818
static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent *event)
824
821
short leftright = RNA_enum_get(op->ptr, "mode");
830
827
/* handle mode-based testing */
831
828
if (leftright == GRAPHKEYS_LRSEL_TEST) {
832
Scene *scene= ac.scene;
834
View2D *v2d= &ar->v2d;
829
Scene *scene = ac.scene;
831
View2D *v2d = &ar->v2d;
837
834
/* determine which side of the current frame mouse is on */
838
835
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, NULL);
840
837
RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT);
842
839
RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT);
846
843
return graphkeys_select_leftright_exec(C, op);
849
void GRAPH_OT_select_leftright (wmOperatorType *ot)
846
void GRAPH_OT_select_leftright(wmOperatorType *ot)
851
850
/* identifiers */
852
851
ot->name = "Select Left/Right";
853
852
ot->idname = "GRAPH_OT_select_leftright";
854
853
ot->description = "Select keyframes to the left or the right of the current frame";
856
855
/* api callbacks */
857
ot->invoke= graphkeys_select_leftright_invoke;
856
ot->invoke = graphkeys_select_leftright_invoke;
858
857
ot->exec = graphkeys_select_leftright_exec;
859
858
ot->poll = graphop_visible_keyframes_poll;
862
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
861
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
865
864
ot->prop = RNA_def_enum(ot->srna, "mode", prop_graphkeys_leftright_select_types, GRAPHKEYS_LRSEL_TEST, "Mode", "");
866
RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
865
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
867
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
868
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
869
871
/* ******************** Mouse-Click Select Operator *********************** */
880
882
typedef struct tNearestVertInfo {
881
883
struct tNearestVertInfo *next, *prev;
883
FCurve *fcu; /* F-Curve that keyframe comes from */
885
BezTriple *bezt; /* keyframe to consider */
886
FPoint *fpt; /* sample point to consider */
888
short hpoint; /* the handle index that we hit (eHandleIndex) */
889
short sel; /* whether the handle is selected or not */
890
int dist; /* distance from mouse to vert */
885
FCurve *fcu; /* F-Curve that keyframe comes from */
887
BezTriple *bezt; /* keyframe to consider */
888
FPoint *fpt; /* sample point to consider */
890
short hpoint; /* the handle index that we hit (eHandleIndex) */
891
short sel; /* whether the handle is selected or not */
892
int dist; /* distance from mouse to vert */
891
893
} tNearestVertInfo;
893
895
/* Tags for the type of graph vert that we have */
894
896
typedef enum eGraphVertIndex {
895
NEAREST_HANDLE_LEFT = -1,
897
NEAREST_HANDLE_LEFT = -1,
896
898
NEAREST_HANDLE_KEY,
897
899
NEAREST_HANDLE_RIGHT
898
900
} eGraphVertIndex;
900
902
/* Tolerance for absolute radius (in pixels) of the vert from the cursor to use */
901
903
// TODO: perhaps this should depend a bit on the size that the user set the vertices to be?
902
#define GVERTSEL_TOL 10
904
#define GVERTSEL_TOL 10
908
910
static int fcurve_handle_sel_check(SpaceIpo *sipo, BezTriple *bezt)
910
912
if (sipo->flag & SIPO_NOHANDLES) return 0;
911
if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZSELECTED(bezt)==0) return 0;
913
if ((sipo->flag & SIPO_SELVHANDLESONLY) && BEZSELECTED(bezt) == 0) return 0;
915
917
/* check if the given vertex is within bounds or not */
916
918
// TODO: should we return if we hit something?
917
static void nearest_fcurve_vert_store (ListBase *matches, View2D *v2d, FCurve *fcu, BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2])
919
static void nearest_fcurve_vert_store(ListBase *matches, View2D *v2d, FCurve *fcu, BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2])
919
921
/* Keyframes or Samples? */
923
925
/* convert from data-space to screen coordinates
924
926
* NOTE: hpoint+1 gives us 0,1,2 respectively for each handle,
925
* needed to access the relevant vertex coordinates in the 3x3
927
* needed to access the relevant vertex coordinates in the 3x3
928
UI_view2d_view_to_region(v2d, bezt->vec[hpoint+1][0], bezt->vec[hpoint+1][1], &screen_co[0], &screen_co[1]);
930
UI_view2d_view_to_region(v2d, bezt->vec[hpoint + 1][0], bezt->vec[hpoint + 1][1], &screen_co[0], &screen_co[1]);
930
932
/* check if distance from mouse cursor to vert in screen space is within tolerance */
931
// XXX: inlined distance calculation, since we cannot do this on ints using the math lib...
933
// XXX: inlined distance calculation, since we cannot do this on ints using the math lib...
932
934
//dist = len_v2v2(mval, screen_co);
933
dist = sqrt((mval[0] - screen_co[0])*(mval[0] - screen_co[0]) +
934
(mval[1] - screen_co[1])*(mval[1] - screen_co[1]));
935
dist = sqrt((mval[0] - screen_co[0]) * (mval[0] - screen_co[0]) +
936
(mval[1] - screen_co[1]) * (mval[1] - screen_co[1]));
936
938
if (dist <= GVERTSEL_TOL) {
937
939
tNearestVertInfo *nvi = (tNearestVertInfo *)matches->last;
940
942
/* if there is already a point for the F-Curve, check if this point is closer than that was */
941
943
if ((nvi) && (nvi->fcu == fcu)) {
942
944
/* replace if we are closer, or if equal and that one wasn't selected but we are... */
943
if ( (nvi->dist > dist) || ((nvi->sel == 0) && BEZSELECTED(bezt)) )
945
if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZSELECTED(bezt)))
946
948
/* add new if not replacing... */
947
949
if (replace == 0)
968
970
/* helper for find_nearest_fcurve_vert() - build the list of nearest matches */
969
static void get_nearest_fcurve_verts_list (bAnimContext *ac, const int mval[2], ListBase *matches)
971
static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], ListBase *matches)
971
973
ListBase anim_data = {NULL, NULL};
972
974
bAnimListElem *ale;
975
SpaceIpo *sipo= (SpaceIpo *)ac->sl;
976
View2D *v2d= &ac->ar->v2d;
977
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
978
View2D *v2d = &ac->ar->v2d;
978
980
/* get curves to search through
979
981
* - if the option to only show keyframes that belong to selected F-Curves is enabled,
980
982
* include the 'only selected' flag...
982
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
983
if (sipo->flag & SIPO_SELCUVERTSONLY) // FIXME: this should really be check for by the filtering code...
984
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
985
if (sipo->flag & SIPO_SELCUVERTSONLY) // FIXME: this should really be check for by the filtering code...
984
986
filter |= ANIMFILTER_SEL;
985
987
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
987
for (ale= anim_data.first; ale; ale= ale->next) {
988
FCurve *fcu= (FCurve *)ale->key_data;
989
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
989
for (ale = anim_data.first; ale; ale = ale->next) {
990
FCurve *fcu = (FCurve *)ale->key_data;
991
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
991
993
/* apply unit corrections */
992
994
ANIM_unit_mapping_apply_fcurve(ac->scene, ale->id, ale->key_data, 0);
996
998
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
998
1000
if (fcu->bezt) {
999
BezTriple *bezt1=fcu->bezt, *prevbezt=NULL;
1001
BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL;
1002
for (i=0; i < fcu->totvert; i++, prevbezt=bezt1, bezt1++) {
1004
for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) {
1004
1006
nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_KEY, mval);
1006
1008
/* handles - only do them if they're visible */
1007
1009
if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
1008
1010
/* first handle only visible if previous segment had handles */
1009
if ((!prevbezt && (bezt1->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ))) {
1011
if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
1010
1012
nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_LEFT, mval);
1047
1049
/* if list only has 1 item, remove it from the list and return */
1048
1050
if (matches->first == matches->last) {
1049
1051
/* need to remove from the list, otherwise it gets freed and then we can't return it */
1050
nvi= matches->first;
1052
nvi = matches->first;
1051
1053
BLI_remlink(matches, nvi);
1081
1083
/* Find the nearest vertices (either a handle or the keyframe) that are nearest to the mouse cursor (in area coordinates)
1082
1084
* NOTE: the match info found must still be freed
1084
static tNearestVertInfo *find_nearest_fcurve_vert (bAnimContext *ac, const int mval[2])
1086
static tNearestVertInfo *find_nearest_fcurve_vert(bAnimContext *ac, const int mval[2])
1086
1088
ListBase matches = {NULL, NULL};
1087
1089
tNearestVertInfo *nvi;
1101
1103
/* ------------------- */
1103
1105
/* option 1) select keyframe directly under mouse */
1104
static void mouse_graph_keys (bAnimContext *ac, const int mval[2], short select_mode, short curves_only)
1106
static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_mode, short curves_only)
1106
SpaceIpo *sipo= (SpaceIpo *)ac->sl;
1108
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
1107
1109
tNearestVertInfo *nvi;
1108
BezTriple *bezt= NULL;
1110
BezTriple *bezt = NULL;
1110
1112
/* find the beztriple that we're selecting, and the handle that was clicked on */
1111
1113
nvi = find_nearest_fcurve_vert(ac, mval);
1113
1115
/* check if anything to select */
1117
1119
/* deselect all other curves? */
1118
1120
if (select_mode == SELECT_REPLACE) {
1119
1121
/* reset selection mode */
1120
select_mode= SELECT_ADD;
1122
select_mode = SELECT_ADD;
1122
1124
/* deselect all other keyframes (+ F-Curves too) */
1123
1125
deselect_graph_keys(ac, 0, SELECT_SUBTRACT, TRUE);
1133
1135
/* if points can be selected on this F-Curve */
1134
1136
// TODO: what about those with no keyframes?
1135
if ((curves_only == 0) && ((nvi->fcu->flag & FCURVE_PROTECTED)==0)) {
1137
if ((curves_only == 0) && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) {
1136
1138
/* only if there's keyframe */
1137
1139
if (nvi->bezt) {
1138
bezt= nvi->bezt; /* used to check bezt seletion is set */
1140
bezt = nvi->bezt; /* used to check bezt seletion is set */
1139
1141
/* depends on selection mode */
1140
1142
if (select_mode == SELECT_INVERT) {
1141
1143
/* keyframe - invert select of all */
1182
1184
memset(&ked, 0, sizeof(KeyframeEditData));
1184
1186
/* set up BezTriple edit callbacks */
1185
select_cb= ANIM_editkeyframes_select(select_mode);
1187
select_cb = ANIM_editkeyframes_select(select_mode);
1187
1189
/* select all keyframes */
1188
1190
ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL);
1212
1214
/* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
1213
1215
/* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) otherwise the active flag won't be set [#26452] */
1214
1216
if (nvi->fcu->flag & FCURVE_SELECTED) {
1215
int filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
1217
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
1216
1218
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, ANIMTYPE_FCURVE);
1224
1226
/* (see graphkeys_select_leftright) */
1226
1228
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
1227
static void graphkeys_mselect_column (bAnimContext *ac, const int mval[2], short select_mode)
1229
static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short select_mode)
1229
ListBase anim_data= {NULL, NULL};
1231
ListBase anim_data = {NULL, NULL};
1230
1232
bAnimListElem *ale;
1239
1241
nvi = find_nearest_fcurve_vert(ac, mval);
1241
1243
/* check if anything to select */
1245
1247
/* get frame number on which elements should be selected */
1246
1248
// TODO: should we restrict to integer frames only?
1248
selx= nvi->bezt->vec[1][0];
1250
selx = nvi->bezt->vec[1][0];
1249
1251
else if (nvi->fpt)
1250
selx= nvi->fpt->vec[0];
1252
selx = nvi->fpt->vec[0];
1252
1254
/* if select mode is replace, deselect all keyframes first */
1253
if (select_mode==SELECT_REPLACE) {
1255
if (select_mode == SELECT_REPLACE) {
1254
1256
/* reset selection mode to add to selection */
1255
select_mode= SELECT_ADD;
1257
select_mode = SELECT_ADD;
1257
1259
/* - deselect all other keyframes, so that just the newly selected remain
1258
1260
* - channels aren't deselected, since we don't re-select any as a consequence
1264
1266
memset(&ked, 0, sizeof(KeyframeEditData));
1266
1268
/* set up BezTriple edit callbacks */
1267
select_cb= ANIM_editkeyframes_select(select_mode);
1268
ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
1269
select_cb = ANIM_editkeyframes_select(select_mode);
1270
ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
1270
1272
/* loop through all of the keys and select additional keyframes
1271
1273
* based on the keys found to be selected above
1273
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
1275
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
1274
1276
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1276
for (ale= anim_data.first; ale; ale= ale->next) {
1277
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
1278
for (ale = anim_data.first; ale; ale = ale->next) {
1279
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1279
1281
/* set frame for validation callback to refer to */
1281
ked.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
1283
ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
1285
1287
/* select elements with frame number matching cfra */
1286
1288
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
1307
1309
/* select mode is either replace (deselect all, then add) or add/extend */
1308
1310
if (RNA_boolean_get(op->ptr, "extend"))
1309
selectmode= SELECT_INVERT;
1311
selectmode = SELECT_INVERT;
1311
selectmode= SELECT_REPLACE;
1313
selectmode = SELECT_REPLACE;
1313
1315
/* figure out action to take */
1314
1316
if (RNA_boolean_get(op->ptr, "column")) {
1327
1329
/* set notifier that keyframe selection (and also channel selection in some cases) has changed */
1328
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|ND_ANIMCHAN|NA_SELECTED, NULL);
1330
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
1330
1332
/* for tweak grab to work */
1331
return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
1333
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
1334
void GRAPH_OT_clickselect (wmOperatorType *ot)
1336
void GRAPH_OT_clickselect(wmOperatorType *ot)
1336
1340
/* identifiers */
1337
1341
ot->name = "Mouse Select Keys";
1338
1342
ot->idname = "GRAPH_OT_clickselect";
1342
1346
ot->invoke = graphkeys_clickselect_invoke;
1343
1347
ot->poll = graphop_visible_keyframes_poll;
1346
RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
1347
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
1348
RNA_def_boolean(ot->srna, "curves", 0, "Only Curves", "Select all the keyframes in the curve"); // CTRLKEY + ALTKEY
1350
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
1351
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1353
prop = RNA_def_boolean(ot->srna, "column", 0, "Column Select",
1354
"Select all keyframes that occur on the same frame as the one under the mouse"); // ALTKEY
1355
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1357
prop = RNA_def_boolean(ot->srna, "curves", 0, "Only Curves",
1358
"Select all the keyframes in the curve"); // CTRLKEY + ALTKEY
1359
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
1351
1362
/* ************************************************************************** */