This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/editors/space_nla/nla_select.c

672 lines
20 KiB
C
Raw Normal View History

/*
* ***** 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.
*
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
* All rights reserved.
*
*
* Contributor(s): Joshua Leung (major recode)
*
* ***** END GPL LICENSE BLOCK *****
*/
2011-02-27 20:29:51 +00:00
/** \file blender/editors/space_nla/nla_select.c
* \ingroup spnla
*/
#include <string.h>
#include <stdio.h>
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "ED_anim_api.h"
#include "ED_keyframes_edit.h"
#include "ED_screen.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
#include "UI_view2d.h"
2012-05-08 18:05:57 +00:00
#include "nla_intern.h" // own include
/* ******************** Utilities ***************************************** */
/* Convert SELECT_* flags to ACHANNEL_SETFLAG_* flags */
2012-05-08 18:05:57 +00:00
static short selmodes_to_flagmodes(short sel)
{
/* convert selection modes to selection modes */
switch (sel) {
case SELECT_SUBTRACT:
return ACHANNEL_SETFLAG_CLEAR;
2014-03-19 12:46:33 +11:00
case SELECT_INVERT:
return ACHANNEL_SETFLAG_INVERT;
2014-03-19 12:46:33 +11:00
case SELECT_ADD:
default:
return ACHANNEL_SETFLAG_ADD;
}
}
/* ******************** 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...
*/
enum {
DESELECT_STRIPS_NOTEST = 0,
DESELECT_STRIPS_TEST,
DESELECT_STRIPS_CLEARACTIVE,
} /*eDeselectNlaStrips*/;
/* Deselects strips in the NLA Editor
* - This is called by the deselect all operator, as well as other ones!
*
2012-05-08 18:05:57 +00:00
* - test: check if select or deselect all (1) or clear all active (2)
* - sel: how to select keyframes
* 0 = deselect
* 1 = select
* 2 = invert
*/
2012-05-08 18:05:57 +00:00
static void deselect_nla_strips(bAnimContext *ac, short test, short sel)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
short smode;
/* determine type-based settings */
Animation Channel Filtering Refactor - Part 3 (Visibility Flag Split) * This (big) commit is aimed at cleaning up the filtering flags used by the animation channel filtering code. The list of filtering flags has been growing a bit "organically" since it's humble origins for use in the Action Editor some 3 years (IIRC) ago now during a weekend hackathon. Obviously, some things have ended up tacked on, while others have been the product of other flag options. Nevertheless, it was time for a bit of a spring clean! * Most notably, one area where the system outgrown its original design for the Action Editor was in terms of the "visibility" filtering flag it was using. While in the Action Editor the concept of what channels to include was strictly dictated by whether the channel hierarchy showed it, in the Graph Editor this is not always the case. In other words, there was a difference between the data the channels represented being visible and the channels for that data being visible in the hierarchy. Long story short: this lead to bug report [#27076] (and many like it), where if you selected an F-Curve, then collapsed the Group it was in, then even after selecting another F-Curve in another Group, the original F-Curve's properties would still be shown in the Properties Region. The good news is that this commit fixes this issue right away! * More good news will follow, as I start checking on the flag usage of other tools, but I'm committing this first so that we have a stable reference (of code similar to the old buggy stuff) on which we can fall back to later to find bugs (should they pop up). Anyways, back to the trenches!
2011-06-22 11:41:26 +00:00
// FIXME: double check whether ANIMFILTER_LIST_VISIBLE is needed!
2012-05-08 18:05:57 +00:00
filter = (ANIMFILTER_DATA_VISIBLE);
/* filter data */
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* See if we should be selecting or deselecting */
if (test == DESELECT_STRIPS_TEST) {
2012-05-08 18:05:57 +00:00
for (ale = anim_data.first; ale; ale = ale->next) {
NlaTrack *nlt = (NlaTrack *)ale->data;
NlaStrip *strip;
/* if any strip is selected, break out, since we should now be deselecting */
2012-05-08 18:05:57 +00:00
for (strip = nlt->strips.first; strip; strip = strip->next) {
if (strip->flag & NLASTRIP_FLAG_SELECT) {
2012-05-08 18:05:57 +00:00
sel = SELECT_SUBTRACT;
break;
}
}
if (sel == SELECT_SUBTRACT)
break;
}
}
/* convert selection modes to selection modes */
2012-05-08 18:05:57 +00:00
smode = selmodes_to_flagmodes(sel);
/* Now set the flags */
2012-05-08 18:05:57 +00:00
for (ale = anim_data.first; ale; ale = ale->next) {
NlaTrack *nlt = (NlaTrack *)ale->data;
NlaStrip *strip;
/* apply same selection to all strips */
2012-05-08 18:05:57 +00:00
for (strip = nlt->strips.first; strip; strip = strip->next) {
/* set selection */
if (test != DESELECT_STRIPS_CLEARACTIVE)
ACHANNEL_SET_FLAG(strip, smode, NLASTRIP_FLAG_SELECT);
/* clear active flag */
// TODO: for clear active, do we want to limit this to only doing this on a certain set of tracks though?
strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
}
}
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int nlaedit_deselectall_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
2012-03-01 12:20:18 +00:00
/* 'standard' behavior - check if selected, then apply relevant selection */
if (RNA_boolean_get(op->ptr, "invert"))
deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT);
else
deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD);
/* set notifier that things have changed */
2012-05-08 18:05:57 +00:00
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
void NLA_OT_select_all_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "(De)select All";
ot->idname = "NLA_OT_select_all_toggle";
ot->description = "Select or deselect all NLA-Strips";
/* api callbacks */
ot->exec = nlaedit_deselectall_exec;
ot->poll = nlaop_poll_tweakmode_off;
/* flags */
2012-05-08 18:05:57 +00:00
ot->flag = OPTYPE_REGISTER /*|OPTYPE_UNDO*/;
/* props */
ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
/* ******************** Border Select Operator **************************** */
/* This operator currently works in one of three ways:
2012-05-08 18:05:57 +00:00
* -> BKEY - 1) all strips within region are selected (NLAEDIT_BORDERSEL_ALLSTRIPS)
* -> ALT-BKEY - depending on which axis of the region was larger...
* -> 2) x-axis, so select all frames within frame range (NLAEDIT_BORDERSEL_FRAMERANGE)
* -> 3) y-axis, so select all frames within channels that region included (NLAEDIT_BORDERSEL_CHANNELS)
*/
/* defines for borderselect mode */
enum {
2012-05-08 18:05:57 +00:00
NLA_BORDERSEL_ALLSTRIPS = 0,
NLA_BORDERSEL_FRAMERANGE,
NLA_BORDERSEL_CHANNELS,
} /* eNLAEDIT_BorderSelect_Mode */;
2012-05-08 18:05:57 +00:00
static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, short selectmode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
SpaceNla *snla = (SpaceNla *)ac->sl;
2012-05-08 18:05:57 +00:00
View2D *v2d = &ac->ar->v2d;
rctf rectf;
2012-05-08 18:05:57 +00:00
float ymin /* =(float)(-NLACHANNEL_HEIGHT(snla)) */ /* UNUSED */, ymax = 0;
/* convert border-region to view coordinates */
2012-05-08 18:05:57 +00:00
UI_view2d_region_to_view(v2d, rect.xmin, rect.ymin + 2, &rectf.xmin, &rectf.ymin);
UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax - 2, &rectf.xmax, &rectf.ymax);
/* filter data */
2012-05-08 18:05:57 +00:00
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* convert selection modes to selection modes */
2012-05-08 18:05:57 +00:00
selectmode = selmodes_to_flagmodes(selectmode);
/* loop over data, doing border select */
2012-05-08 18:05:57 +00:00
for (ale = anim_data.first; ale; ale = ale->next) {
ymin = ymax - NLACHANNEL_STEP(snla);
/* perform vertical suitability check (if applicable) */
if ((mode == NLA_BORDERSEL_FRAMERANGE) ||
!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
{
/* loop over data selecting (only if NLA-Track) */
if (ale->type == ANIMTYPE_NLATRACK) {
2012-05-08 18:05:57 +00:00
NlaTrack *nlt = (NlaTrack *)ale->data;
NlaStrip *strip;
/* only select strips if they fall within the required ranges (if applicable) */
2012-05-08 18:05:57 +00:00
for (strip = nlt->strips.first; strip; strip = strip->next) {
if ((mode == NLA_BORDERSEL_CHANNELS) ||
BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax))
{
/* set selection */
ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT);
/* clear active flag */
strip->flag &= ~NLASTRIP_FLAG_ACTIVE;
}
}
}
}
/* set minimum extent to be the maximum of the next channel */
2012-05-08 18:05:57 +00:00
ymax = ymin;
}
/* cleanup */
ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
rcti rect;
2012-05-08 18:05:57 +00:00
short mode = 0, selectmode = 0;
const bool select = !RNA_boolean_get(op->ptr, "deselect");
const bool extend = RNA_boolean_get(op->ptr, "extend");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
/* clear all selection if not extending selection */
if (!extend) {
deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_SUBTRACT);
}
/* get settings from operator */
WM_operator_properties_border_to_rcti(op, &rect);
if (select) {
selectmode = SELECT_ADD;
}
else {
selectmode = SELECT_SUBTRACT;
}
/* 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
2012-03-01 12:20:18 +00:00
* - the frame-range select option is favored 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 (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect))
2012-05-08 18:05:57 +00:00
mode = NLA_BORDERSEL_FRAMERANGE;
else
2012-05-08 18:05:57 +00:00
mode = NLA_BORDERSEL_CHANNELS;
}
else
2012-05-08 18:05:57 +00:00
mode = NLA_BORDERSEL_ALLSTRIPS;
/* apply borderselect action */
borderselect_nla_strips(&ac, rect, mode, selectmode);
/* set notifier that things have changed */
2012-05-08 18:05:57 +00:00
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
return OPERATOR_FINISHED;
}
void NLA_OT_select_border(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Border Select";
ot->idname = "NLA_OT_select_border";
ot->description = "Use box selection to grab NLA-Strips";
/* api callbacks */
ot->invoke = WM_gesture_border_invoke;
ot->exec = nlaedit_borderselect_exec;
ot->modal = WM_gesture_border_modal;
ot->cancel = WM_gesture_border_cancel;
ot->poll = nlaop_poll_tweakmode_off;
/* flags */
2012-05-08 18:05:57 +00:00
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* rna */
WM_operator_properties_gesture_border_select(ot);
RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
}
2011-02-14 03:04:59 +00:00
/* ******************** Select Left/Right Operator ************************* */
/* Select keyframes left/right of the current frame indicator */
/* defines for left-right select tool */
static EnumPropertyItem prop_nlaedit_leftright_select_types[] = {
{NLAEDIT_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
{NLAEDIT_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
{NLAEDIT_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
{0, NULL, 0, NULL, NULL}
};
2011-02-14 03:04:59 +00:00
/* ------------------- */
2012-05-08 18:05:57 +00:00
static void nlaedit_select_leftright(bContext *C, bAnimContext *ac, short leftright, short select_mode)
2011-02-14 03:04:59 +00:00
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
2012-05-08 18:05:57 +00:00
Scene *scene = ac->scene;
2011-02-14 03:04:59 +00:00
float xmin, xmax;
/* if currently in tweakmode, exit tweakmode first */
if (scene->flag & SCE_NLA_EDIT_ON)
WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
/* if select mode is replace, deselect all keyframes (and channels) first */
2012-05-08 18:05:57 +00:00
if (select_mode == SELECT_REPLACE) {
select_mode = SELECT_ADD;
2011-02-14 03:04:59 +00:00
/* - deselect all other keyframes, so that just the newly selected remain
* - channels aren't deselected, since we don't re-select any as a consequence
*/
2011-02-14 03:04:59 +00:00
deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
}
/* get range, and get the right flag-setting mode */
if (leftright == NLAEDIT_LRSEL_LEFT) {
xmin = MINAFRAMEF;
xmax = (float)(CFRA + 0.1f);
}
2011-02-14 03:04:59 +00:00
else {
xmin = (float)(CFRA - 0.1f);
xmax = MAXFRAMEF;
}
2012-05-08 18:05:57 +00:00
select_mode = selmodes_to_flagmodes(select_mode);
2011-02-14 03:04:59 +00:00
/* filter data */
2012-05-08 18:05:57 +00:00
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
2011-02-14 03:04:59 +00:00
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* select strips on the side where most data occurs */
2012-05-08 18:05:57 +00:00
for (ale = anim_data.first; ale; ale = ale->next) {
NlaTrack *nlt = (NlaTrack *)ale->data;
2011-02-14 03:04:59 +00:00
NlaStrip *strip;
/* check each strip to see if it is appropriate */
2012-05-08 18:05:57 +00:00
for (strip = nlt->strips.first; strip; strip = strip->next) {
2011-02-14 03:04:59 +00:00
if (BKE_nlastrip_within_bounds(strip, xmin, xmax)) {
ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
}
}
}
/* Cleanup */
ANIM_animdata_freelist(&anim_data);
2011-02-14 03:04:59 +00:00
}
/* ------------------- */
2012-05-08 18:05:57 +00:00
static int nlaedit_select_leftright_exec(bContext *C, wmOperator *op)
2011-02-14 03:04:59 +00:00
{
bAnimContext ac;
short leftright = RNA_enum_get(op->ptr, "mode");
short selectmode;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
/* select mode is either replace (deselect all, then add) or add/extend */
if (RNA_boolean_get(op->ptr, "extend"))
2012-05-08 18:05:57 +00:00
selectmode = SELECT_INVERT;
2011-02-14 03:04:59 +00:00
else
2012-05-08 18:05:57 +00:00
selectmode = SELECT_REPLACE;
2011-02-14 03:04:59 +00:00
/* if "test" mode is set, we don't have any info to set this with */
if (leftright == NLAEDIT_LRSEL_TEST)
return OPERATOR_CANCELLED;
/* do the selecting now */
nlaedit_select_leftright(C, &ac, leftright, selectmode);
/* set notifier that keyframe selection (and channels too) have changed */
2012-05-08 18:05:57 +00:00
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL);
2011-02-14 03:04:59 +00:00
return OPERATOR_FINISHED;
}
static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2011-02-14 03:04:59 +00:00
{
bAnimContext ac;
short leftright = RNA_enum_get(op->ptr, "mode");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
/* handle mode-based testing */
if (leftright == NLAEDIT_LRSEL_TEST) {
2012-05-08 18:05:57 +00:00
Scene *scene = ac.scene;
ARegion *ar = ac.ar;
View2D *v2d = &ar->v2d;
2011-02-14 03:04:59 +00:00
float x;
/* determine which side of the current frame mouse is on */
x = UI_view2d_region_to_view_x(v2d, event->mval[0]);
2011-02-14 03:04:59 +00:00
if (x < CFRA)
2014-07-06 20:54:08 +10:00
RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_LEFT);
else
2014-07-06 20:54:08 +10:00
RNA_enum_set(op->ptr, "mode", NLAEDIT_LRSEL_RIGHT);
2011-02-14 03:04:59 +00:00
}
/* perform selection */
return nlaedit_select_leftright_exec(C, op);
}
void NLA_OT_select_leftright(wmOperatorType *ot)
2011-02-14 03:04:59 +00:00
{
PropertyRNA *prop;
2011-02-14 03:04:59 +00:00
/* identifiers */
ot->name = "Select Left/Right";
ot->idname = "NLA_OT_select_leftright";
ot->description = "Select strips to the left or the right of the current frame";
2011-02-14 03:04:59 +00:00
/* api callbacks */
ot->invoke = nlaedit_select_leftright_invoke;
ot->exec = nlaedit_select_leftright_exec;
ot->poll = ED_operator_nla_active;
2011-02-14 03:04:59 +00:00
/* flags */
2012-05-08 18:05:57 +00:00
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2011-02-14 03:04:59 +00:00
/* properties */
ot->prop = RNA_def_enum(ot->srna, "mode", prop_nlaedit_leftright_select_types, NLAEDIT_LRSEL_TEST, "Mode", "");
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2011-02-14 03:04:59 +00:00
}
/* ******************** Mouse-Click Select Operator *********************** */
/* select strip directly under mouse */
2012-05-08 18:05:57 +00:00
static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], short select_mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale = NULL;
int filter;
SpaceNla *snla = (SpaceNla *)ac->sl;
2012-05-08 18:05:57 +00:00
View2D *v2d = &ac->ar->v2d;
Scene *scene = ac->scene;
NlaStrip *strip = NULL;
int channel_index;
float xmin, xmax;
float x, y;
/* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
UI_view2d_listview_view_to_cell(v2d, 0, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
/* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
* (that is the size of keyframe icons, so user should be expecting similar tolerances)
*/
xmin = UI_view2d_region_to_view_x(v2d, mval[0] - 7);
xmax = UI_view2d_region_to_view_x(v2d, mval[0] + 7);
/* filter data */
2012-05-08 18:05:57 +00:00
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* try to get channel */
2012-05-08 18:05:57 +00:00
ale = BLI_findlink(&anim_data, channel_index);
if (ale == NULL) {
/* channel not found */
printf("Error: animation channel (index = %d) not found in mouse_nla_strips()\n", channel_index);
ANIM_animdata_freelist(&anim_data);
return;
}
else {
/* found some channel - we only really should do somethign when its an Nla-Track */
if (ale->type == ANIMTYPE_NLATRACK) {
2012-05-08 18:05:57 +00:00
NlaTrack *nlt = (NlaTrack *)ale->data;
/* loop over NLA-strips in this track, trying to find one which occurs in the necessary bounds */
2012-05-08 18:05:57 +00:00
for (strip = nlt->strips.first; strip; strip = strip->next) {
if (BKE_nlastrip_within_bounds(strip, xmin, xmax))
break;
}
}
/* remove active channel from list of channels for separate treatment (since it's needed later on) */
BLI_remlink(&anim_data, ale);
/* free list of channels, since it's not used anymore */
ANIM_animdata_freelist(&anim_data);
}
/* if currently in tweakmode, exit tweakmode before changing selection states
* now that we've found our target...
*/
if (scene->flag & SCE_NLA_EDIT_ON)
WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
/* for replacing selection, firstly need to clear existing selection */
if (select_mode == SELECT_REPLACE) {
/* reset selection mode for next steps */
select_mode = SELECT_ADD;
/* deselect all strips */
deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
/* deselect all other channels first */
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
}
/* only select strip if we clicked on a valid channel and hit something */
if (ale) {
/* select the strip accordingly (if a matching one was found) */
if (strip) {
2012-05-08 18:05:57 +00:00
select_mode = selmodes_to_flagmodes(select_mode);
ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
/* if we selected it, we can make it active too
* - we always need to clear the active strip flag though...
* - as well as selecting its track...
*/
deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0);
if (strip->flag & NLASTRIP_FLAG_SELECT) {
strip->flag |= NLASTRIP_FLAG_ACTIVE;
/* Highlight NLA-Track */
if (ale->type == ANIMTYPE_NLATRACK) {
NlaTrack *nlt = (NlaTrack *)ale->data;
nlt->flag |= NLATRACK_SELECTED;
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
}
}
}
/* free this channel */
MEM_freeN(ale);
}
}
/* ------------------- */
/* handle clicking */
static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
/* Scene *scene; */ /* UNUSED */
/* ARegion *ar; */ /* UNUSED */
// View2D *v2d; /*UNUSED*/
short selectmode;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
/* get useful pointers from animation context data */
/* scene= ac.scene; */ /* UNUSED */
/* ar= ac.ar; */ /* UNUSED */
// v2d= &ar->v2d;
/* select mode is either replace (deselect all, then add) or add/extend */
if (RNA_boolean_get(op->ptr, "extend"))
2012-05-08 18:05:57 +00:00
selectmode = SELECT_INVERT;
else
2012-05-08 18:05:57 +00:00
selectmode = SELECT_REPLACE;
2011-02-14 03:04:59 +00:00
/* select strips based upon mouse position */
mouse_nla_strips(C, &ac, event->mval, selectmode);
/* set notifier that things have changed */
2012-05-08 18:05:57 +00:00
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
/* for tweak grab to work */
2012-05-08 18:05:57 +00:00
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
void NLA_OT_click_select(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Mouse Select";
ot->idname = "NLA_OT_click_select";
ot->description = "Handle clicks to select NLA Strips";
/* api callbacks - absolutely no exec() this yet... */
ot->invoke = nlaedit_clickselect_invoke;
ot->poll = ED_operator_nla_active;
/* flags */
ot->flag = OPTYPE_UNDO;
/* properties */
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* *********************************************** */