Graph Editor: add lasso select for fcurves
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_lasso.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
@@ -523,6 +524,45 @@ static short ok_bezier_region(KeyframeEditData *ked, BezTriple *bezt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* only called from #ok_bezier_region_lasso
|
||||
*/
|
||||
static bool bezier_region_lasso_test(
|
||||
const struct KeyframeEdit_LassoData *data_lasso,
|
||||
const float xy[2])
|
||||
{
|
||||
if (BLI_rctf_isect_pt_v(data_lasso->rectf_scaled, xy)) {
|
||||
float xy_view[2];
|
||||
|
||||
BLI_rctf_transform_pt_v(data_lasso->rectf_view, data_lasso->rectf_scaled, xy_view, xy);
|
||||
|
||||
if (BLI_lasso_is_point_inside(data_lasso->mcords, data_lasso->mcords_tot, xy_view[0], xy_view[1], INT_MAX)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static short ok_bezier_region_lasso(KeyframeEditData *ked, BezTriple *bezt)
|
||||
{
|
||||
/* rect is stored in data property (it's of type rectf, but may not be set) */
|
||||
if (ked->data) {
|
||||
short ok = 0;
|
||||
|
||||
#define KEY_CHECK_OK(_index) bezier_region_lasso_test(ked->data, bezt->vec[_index])
|
||||
KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
|
||||
#undef KEY_CHECK_OK
|
||||
|
||||
/* check for lasso */
|
||||
|
||||
/* return ok flags */
|
||||
return ok;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
|
||||
{
|
||||
@@ -540,6 +580,8 @@ KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
|
||||
return ok_bezier_valuerange;
|
||||
case BEZT_OK_REGION: /* only if bezier falls within the specified rect (data -> rectf) */
|
||||
return ok_bezier_region;
|
||||
case BEZT_OK_REGION_LASSO: /* only if the point falls within KeyframeEdit_LassoData defined data */
|
||||
return ok_bezier_region_lasso;
|
||||
default: /* nothing was ok */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,8 @@ typedef enum eEditKeyframes_Validate {
|
||||
BEZT_OK_SELECTED,
|
||||
BEZT_OK_VALUE,
|
||||
BEZT_OK_VALUERANGE,
|
||||
BEZT_OK_REGION
|
||||
BEZT_OK_REGION,
|
||||
BEZT_OK_REGION_LASSO,
|
||||
} eEditKeyframes_Validate;
|
||||
|
||||
/* ------------ */
|
||||
@@ -98,6 +99,15 @@ typedef enum eEditKeyframes_Mirror {
|
||||
MIRROR_KEYS_VALUE
|
||||
} eEditKeyframes_Mirror;
|
||||
|
||||
/* use with BEZT_OK_REGION_LASSO */
|
||||
struct KeyframeEdit_LassoData {
|
||||
const rctf *rectf_scaled;
|
||||
const rctf *rectf_view;
|
||||
const int (*mcords)[2];
|
||||
int mcords_tot;
|
||||
};
|
||||
|
||||
|
||||
/* ************************************************ */
|
||||
/* Non-Destuctive Editing API (keyframes_edit.c) */
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ void graph_draw_ghost_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, str
|
||||
|
||||
void GRAPH_OT_select_all_toggle(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_select_border(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_select_lasso(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_select_column(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_select_linked(struct wmOperatorType *ot);
|
||||
void GRAPH_OT_select_more(struct wmOperatorType *ot);
|
||||
|
||||
@@ -213,6 +213,7 @@ void graphedit_operatortypes(void)
|
||||
WM_operatortype_append(GRAPH_OT_clickselect);
|
||||
WM_operatortype_append(GRAPH_OT_select_all_toggle);
|
||||
WM_operatortype_append(GRAPH_OT_select_border);
|
||||
WM_operatortype_append(GRAPH_OT_select_lasso);
|
||||
WM_operatortype_append(GRAPH_OT_select_column);
|
||||
WM_operatortype_append(GRAPH_OT_select_linked);
|
||||
WM_operatortype_append(GRAPH_OT_select_more);
|
||||
@@ -344,7 +345,12 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
|
||||
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_border", BKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "axis_range", TRUE);
|
||||
RNA_boolean_set(kmi->ptr, "include_handles", TRUE);
|
||||
|
||||
|
||||
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
|
||||
RNA_boolean_set(kmi->ptr, "deselect", false);
|
||||
kmi = WM_keymap_add_item(keymap, "GRAPH_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
|
||||
RNA_boolean_set(kmi->ptr, "deselect", true);
|
||||
|
||||
/* column select */
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_KEYS);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "GRAPH_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", GRAPHKEYS_COLUMNSEL_CFRA);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_lasso.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
@@ -217,7 +218,9 @@ void GRAPH_OT_select_all_toggle(wmOperatorType *ot)
|
||||
* this, and allow handles to be considered independently too.
|
||||
* 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, short incl_handles)
|
||||
static void borderselect_graphkeys(
|
||||
bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, bool incl_handles,
|
||||
struct KeyframeEdit_LassoData *data_lasso)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
@@ -230,8 +233,8 @@ static void borderselect_graphkeys(bAnimContext *ac, rcti rect, short mode, shor
|
||||
rctf rectf, scaled_rectf;
|
||||
|
||||
/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
|
||||
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);
|
||||
UI_view2d_region_to_view(v2d, rectf_view->xmin, rectf_view->ymin, &rectf.xmin, &rectf.ymin);
|
||||
UI_view2d_region_to_view(v2d, rectf_view->xmax, rectf_view->ymax, &rectf.xmax, &rectf.ymax);
|
||||
|
||||
/* filter data */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
|
||||
@@ -243,7 +246,13 @@ static void borderselect_graphkeys(bAnimContext *ac, rcti rect, short mode, shor
|
||||
|
||||
/* init editing data */
|
||||
memset(&ked, 0, sizeof(KeyframeEditData));
|
||||
ked.data = &scaled_rectf;
|
||||
if (data_lasso) {
|
||||
data_lasso->rectf_scaled = &scaled_rectf;
|
||||
ked.data = data_lasso;
|
||||
}
|
||||
else {
|
||||
ked.data = &scaled_rectf;
|
||||
}
|
||||
|
||||
/* treat handles separately? */
|
||||
if (incl_handles) {
|
||||
@@ -313,9 +322,10 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
rcti rect;
|
||||
rctf rect_fl;
|
||||
short mode = 0, selectmode = 0;
|
||||
short incl_handles;
|
||||
int extend;
|
||||
bool incl_handles;
|
||||
bool extend;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
@@ -354,9 +364,11 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
else
|
||||
mode = BEZT_OK_REGION;
|
||||
|
||||
|
||||
BLI_rctf_rcti_copy(&rect_fl, &rect);
|
||||
|
||||
/* apply borderselect action */
|
||||
borderselect_graphkeys(&ac, rect, mode, selectmode, incl_handles);
|
||||
borderselect_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL);
|
||||
|
||||
/* send notifier that keyframe selection has changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
|
||||
@@ -389,6 +401,92 @@ void GRAPH_OT_select_border(wmOperatorType *ot)
|
||||
RNA_def_boolean(ot->srna, "include_handles", 0, "Include Handles", "Are handles tested individually against the selection criteria");
|
||||
}
|
||||
|
||||
static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
rcti rect;
|
||||
rctf rect_fl;
|
||||
short selectmode;
|
||||
bool incl_handles;
|
||||
bool extend;
|
||||
|
||||
struct KeyframeEdit_LassoData data_lasso;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
data_lasso.rectf_view = &rect_fl;
|
||||
data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot);
|
||||
if (data_lasso.mcords == NULL)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* clear all selection if not extending selection */
|
||||
extend = RNA_boolean_get(op->ptr, "extend");
|
||||
if (!extend)
|
||||
deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, TRUE);
|
||||
|
||||
if (!RNA_boolean_get(op->ptr, "deselect"))
|
||||
selectmode = SELECT_ADD;
|
||||
else
|
||||
selectmode = SELECT_SUBTRACT;
|
||||
|
||||
if (ac.spacetype == SPACE_IPO) {
|
||||
SpaceIpo *sipo = (SpaceIpo *)ac.sl;
|
||||
if (selectmode == SELECT_ADD) {
|
||||
incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) ||
|
||||
(sipo->flag & SIPO_NOHANDLES)) == 0;
|
||||
}
|
||||
else {
|
||||
incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
incl_handles = false;
|
||||
}
|
||||
|
||||
|
||||
/* get settings from operator */
|
||||
BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
|
||||
|
||||
BLI_rctf_rcti_copy(&rect_fl, &rect);
|
||||
|
||||
/* apply borderselect action */
|
||||
borderselect_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso);
|
||||
|
||||
MEM_freeN((void *)data_lasso.mcords);
|
||||
|
||||
|
||||
/* send notifier that keyframe selection has changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
void GRAPH_OT_select_lasso(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Lasso Select";
|
||||
ot->description = "Select keyframe points using lasso selection";
|
||||
ot->idname = "GRAPH_OT_select_lasso";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = WM_gesture_lasso_invoke;
|
||||
ot->modal = WM_gesture_lasso_modal;
|
||||
ot->exec = graphkeys_lassoselect_exec;
|
||||
ot->poll = graphop_visible_keyframes_poll;
|
||||
ot->cancel = WM_gesture_lasso_cancel;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
|
||||
RNA_def_boolean(ot->srna, "deselect", false, "Deselect", "Deselect rather than select items");
|
||||
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection instead of deselecting everything first");
|
||||
}
|
||||
|
||||
/* ******************** Column Select Operator **************************** */
|
||||
/* This operator works in one of four ways:
|
||||
* - 1) select all keyframes in the same frame as a selected one (KKEY)
|
||||
|
||||
Reference in New Issue
Block a user