示例#1
0
/* Deselects keyframes in the Graph Editor
 *	- 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
 *	- do_channels: whether to affect selection status of channels
 */
static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short do_channels)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	SpaceIpo *sipo = (SpaceIpo *)ac->sl;
	KeyframeEditData ked = {{NULL}};
	KeyframeEditFunc test_cb, sel_cb;
	
	/* determine type-based settings */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
	
	/* filter data */
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* init BezTriple looping data */
	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) {
			if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
				sel = SELECT_SUBTRACT;
				break;
			}
		}
	}
	
	/* convert sel to selectmode, and use that to get editor */
	sel_cb = ANIM_editkeyframes_select(sel);
	
	/* Now set the flags */
	for (ale = anim_data.first; ale; ale = ale->next) {
		FCurve *fcu = (FCurve *)ale->key_data;
		
		/* Keyframes First */
		ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
		
		/* affect channel selection status? */
		if (do_channels) {
			/* only change selection of channel when the visibility of keyframes doesn't depend on this */
			if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
				/* deactivate the F-Curve, and deselect if deselecting keyframes.
				 * otherwise select the F-Curve too since we've selected all the keyframes
				 */
				if (sel == SELECT_SUBTRACT) 
					fcu->flag &= ~FCURVE_SELECTED;
				else
					fcu->flag |= FCURVE_SELECTED;
			}
			
			/* always deactivate all F-Curves if we perform batch ops for selection */
			fcu->flag &= ~FCURVE_ACTIVE;
		}
	}
	
	/* Cleanup */
	BLI_freelistN(&anim_data);
}
示例#2
0
/* option 1) select keyframe directly under mouse */
static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
{
	KeyframeEditData ked = {{NULL}};
	KeyframeEditFunc select_cb, ok_cb;
	
	/* get functions for selecting keyframes */
	select_cb = ANIM_editkeyframes_select(select_mode);
	ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAME);
	ked.f1 = selx;
	
	/* select the nominated keyframe on the given frame */
	if (ale->type == ANIMTYPE_GPLAYER)
		ED_gpencil_select_frame(ale->data, selx, select_mode);
	else if (ale->type == ANIMTYPE_MASKLAYER)
		ED_mask_select_frame(ale->data, selx, select_mode);
	else {
		if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) &&
		    (ale->type == ANIMTYPE_SUMMARY) && (ale->datatype == ALE_ALL))
		{
			ListBase anim_data = {NULL, NULL};
			int filter;
			filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
			ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
			for (ale = anim_data.first; ale; ale = ale->next) {
				if (ale->type == ANIMTYPE_GPLAYER)
					ED_gpencil_select_frame(ale->data, selx, select_mode);
				else if (ale->type == ANIMTYPE_MASKLAYER)
					ED_mask_select_frame(ale->data, selx, select_mode);
			}
		}
		else {
			ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
		}
	}
}
示例#3
0
/* Deselects keyframes in the action editor
 *	- 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 (SELECT_*)
 */
static void deselect_action_keys (bAnimContext *ac, short test, short sel)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditData ked= {{NULL}};
	KeyframeEditFunc test_cb, sel_cb;
	
	/* determine type-based settings */
	if (ac->datatype == ANIMCONT_GPENCIL)
		filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
	else
		filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	
	/* filter data */
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* init BezTriple looping data */
	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) {
			if (ale->type == ANIMTYPE_GPLAYER) {
				if (is_gplayer_frame_selected(ale->data)) {
					sel= SELECT_SUBTRACT;
					break;
				}
			}
			else {
				if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
					sel= SELECT_SUBTRACT;
					break;
				}
			}
		}
	}
	
	/* convert sel to selectmode, and use that to get editor */
	sel_cb= ANIM_editkeyframes_select(sel);
	
	/* Now set the flags */
	for (ale= anim_data.first; ale; ale= ale->next) {
		if (ale->type == ANIMTYPE_GPLAYER)
			set_gplayer_frame_selection(ale->data, sel);
		else
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); 
	}
	
	/* Cleanup */
	BLI_freelistN(&anim_data);
}
示例#4
0
static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditFunc ok_cb, select_cb;
	KeyframeEditData ked = {{NULL}};
	Scene *scene = ac->scene;
	
	/* if select mode is replace, deselect all keyframes (and channels) first */
	if (select_mode == SELECT_REPLACE) {
		select_mode = SELECT_ADD;
		
		/* - 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
		 */
		deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
	}
	
	/* set callbacks and editing data */
	ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
	select_cb = ANIM_editkeyframes_select(select_mode);
	
	if (leftright == GRAPHKEYS_LRSEL_LEFT) {
		ked.f1 = MINAFRAMEF;
		ked.f2 = (float)(CFRA + 0.1f);
	}
	else {
		ked.f1 = (float)(CFRA - 0.1f);
		ked.f2 = MAXFRAMEF;
	}
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
		
	/* select keys */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		if (adt) {
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
		}
		else
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
	}

	/* Cleanup */
	BLI_freelistN(&anim_data);
}
示例#5
0
/* TODO, this is almost an _exact_ duplicate of a function of the same name in graph_select.c
 * should de-duplicate - campbell */
static void markers_selectkeys_between(bAnimContext *ac)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditFunc ok_cb, select_cb;
	KeyframeEditData ked = {{NULL}};
	float min, max;
	
	/* get extreme markers */
	ED_markers_get_minmax(ac->markers, 1, &min, &max);
	min -= 0.5f;
	max += 0.5f;
	
	/* get editing funcs + data */
	ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
	select_cb = ANIM_editkeyframes_select(SELECT_ADD);

	ked.f1 = min;
	ked.f2 = max;
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* select keys in-between */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		if (adt) {
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
		}
		else if (ale->type == ANIMTYPE_GPLAYER) {
			ED_gplayer_frames_select_border(ale->data, min, max, SELECT_ADD);
		}
		else if (ale->type == ANIMTYPE_MASKLAYER) {
			ED_masklayer_frames_select_border(ale->data, min, max, SELECT_ADD);
		}
		else {
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
		}
	}
	
	/* Cleanup */
	ANIM_animdata_freelist(&anim_data);
}
示例#6
0
/* option 1) select keyframe directly under mouse */
static void actkeys_mselect_single (bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
{
	KeyframeEditData ked= {{NULL}};
	KeyframeEditFunc select_cb, ok_cb;
	
	/* get functions for selecting keyframes */
	select_cb= ANIM_editkeyframes_select(select_mode);
	ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
	ked.f1= selx;
	
	/* select the nominated keyframe on the given frame */
	if (ale->type == ANIMTYPE_GPLAYER)
		select_gpencil_frame(ale->data, selx, select_mode);
	else
		ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
}
示例#7
0
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float selx)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditFunc select_cb, ok_cb;
	KeyframeEditData ked = {{NULL}};
	
	/* set up BezTriple edit callbacks */
	select_cb = ANIM_editkeyframes_select(select_mode);
	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
	 */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		/* set frame for validation callback to refer to */
		if (adt)
			ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
		else
			ked.f1 = selx;
		
		/* select elements with frame number matching cfra */
		if (ale->type == ANIMTYPE_GPLAYER)
			ED_gpencil_select_frame(ale->key_data, selx, select_mode);
		else if (ale->type == ANIMTYPE_MASKLAYER)
			ED_mask_select_frame(ale->key_data, selx, select_mode);
		else
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
	}
	
	/* free elements */
	BLI_freelistN(&ked.list);
	ANIM_animdata_freelist(&anim_data);
}
示例#8
0
/* option 4) select all keyframes in same channel */
static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, short select_mode)
{
	KeyframeEditFunc select_cb;
	
	/* get functions for selecting keyframes */
	select_cb = ANIM_editkeyframes_select(select_mode);
	
	/* select all keyframes in this channel */
	if (ale->type == ANIMTYPE_GPLAYER) {
		ED_gpencil_select_frames(ale->data, select_mode);
	}
	else if (ale->type == ANIMTYPE_MASKLAYER) {
		ED_mask_select_frames(ale->data, select_mode);
	}
	else {
		if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK) &&
		    (ale->type == ANIMTYPE_SUMMARY) && (ale->datatype == ALE_ALL))
		{
			ListBase anim_data = {NULL, NULL};
			int filter;
			
			filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
			ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
			
			for (ale = anim_data.first; ale; ale = ale->next) {
				if (ale->type == ANIMTYPE_GPLAYER) {
					ED_gpencil_select_frames(ale->data, select_mode);
				}
				else if (ale->type == ANIMTYPE_MASKLAYER) {
					ED_mask_select_frames(ale->data, select_mode);
				}
			}
			
			ANIM_animdata_freelist(&anim_data);
		}
		else {
			ANIM_animchannel_keyframes_loop(NULL, ac->ads, ale, NULL, select_cb, NULL);
		}
	}
}
示例#9
0
static int graphkeys_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
	bAnimContext ac;
	
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
	KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD);
	
	/* get editor data */
	if (ANIM_animdata_get_context(C, &ac) == 0)
		return OPERATOR_CANCELLED;
	
	/* loop through all of the keys and select additional keyframes based on these */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
	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;
		
		/* check if anything selected? */
		if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
			/* select every keyframe in this curve then */
			ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
		}
	}
	
	/* Cleanup */
	BLI_freelistN(&anim_data);
	
	/* set notifier that keyframe selection has changed */
	WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
	
	return OPERATOR_FINISHED;
}
示例#10
0
static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view, short mode, short selectmode, void *data)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditData ked;
	KeyframeEditFunc ok_cb, select_cb;
	View2D *v2d = &ac->ar->v2d;
	rctf rectf, scaled_rectf;
	float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));
	
	/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
	UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* get beztriple editing/validation funcs  */
	select_cb = ANIM_editkeyframes_select(selectmode);
	ok_cb = ANIM_editkeyframes_ok(mode);
	
	/* init editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));
	if (mode == BEZT_OK_CHANNEL_LASSO) {
		KeyframeEdit_LassoData *data_lasso = data;
		data_lasso->rectf_scaled = &scaled_rectf;
		ked.data = data_lasso;
	}
	else if (mode == BEZT_OK_CHANNEL_CIRCLE) {
		KeyframeEdit_CircleData *data_circle = data;
		data_circle->rectf_scaled = &scaled_rectf;
		ked.data = data;
	}
	else {
		ked.data = &scaled_rectf;
	}
	
	/* loop over data, doing region select */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		/* get new vertical minimum extent of channel */
		ymin = ymax - ACHANNEL_STEP(ac);
		
		/* compute midpoint of channel (used for testing if the key is in the region or not) */
		ked.channel_y = ymin + ACHANNEL_HEIGHT_HALF(ac);
		
		/* if channel is mapped in NLA, apply correction
		 * - Apply to the bounds being checked, not all the keyframe points,
		 *   to avoid having scaling everything
		 * - Save result to the scaled_rect, which is all that these operators
		 *   will read from
		 */
		if (adt) {
			ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
			ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
			ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
		}
		else {
			ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
			ked.f1 = rectf.xmin;
			ked.f2 = rectf.xmax;
		}
		
		/* Update values for scaled_rectf - which is used to compute the mapping in the callbacks
		 * NOTE: Since summary tracks need late-binding remapping, the callbacks may overwrite these 
		 *       with the properly remapped ked.f1/f2 values, when needed
		 */
		scaled_rectf.xmin = ked.f1;
		scaled_rectf.xmax = ked.f2;
		scaled_rectf.ymin = ymin;
		scaled_rectf.ymax = ymax;
		
		/* perform vertical suitability check (if applicable) */
		if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) ||
		    !((ymax < rectf.ymin) || (ymin > rectf.ymax)))
		{
			/* loop over data selecting */
			switch (ale->type) {
#if 0 /* XXX: Keyframes are not currently shown here */
				case ANIMTYPE_GPDATABLOCK:
				{
					bGPdata *gpd = ale->data;
					bGPDlayer *gpl;
					for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
						ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
					}
					break;
				}
#endif
				case ANIMTYPE_GPLAYER:
				{
					ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
					break;
				}
				case ANIMTYPE_MASKDATABLOCK:
				{
					Mask *mask = ale->data;
					MaskLayer *masklay;
					for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
						ED_masklayer_frames_select_region(&ked, masklay, mode, selectmode);
					}
					break;
				}
				case ANIMTYPE_MASKLAYER:
				{
					ED_masklayer_frames_select_region(&ked, ale->data, mode, selectmode);
					break;
				}
				default:
					ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
					break;
			}
		}
		
		/* set minimum extent to be the maximum of the next channel */
		ymax = ymin;
	}
	
	/* cleanup */
	ANIM_animdata_freelist(&anim_data);
}
示例#11
0
/* 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;
	KeyframeEditFunc select_cb, ok_cb;
	KeyframeEditData ked;
	
	/* initialize keyframe editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));
	
	/* build list of columns */
	switch (mode) {
		case GRAPHKEYS_COLUMNSEL_KEYS: /* list of selected keys */
			filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
			ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
			
			for (ale = anim_data.first; ale; ale = ale->next)
				ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
			
			BLI_freelistN(&anim_data);
			break;
			
		case GRAPHKEYS_COLUMNSEL_CFRA: /* current frame */
			/* make a single CfraElem for storing this */
			ce = MEM_callocN(sizeof(CfraElem), "cfraElem");
			BLI_addtail(&ked.list, ce);
			
			ce->cfra = (float)CFRA;
			break;
			
		case GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
			ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
			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
	 */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		/* loop over cfraelems (stored in the KeyframeEditData->list)
		 *	- we need to do this here, as we can apply fewer NLA-mapping conversions
		 */
		for (ce = ked.list.first; ce; ce = ce->next) {
			/* set frame for validation callback to refer to */
			ked.f1 = BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);

			/* select elements with frame number matching cfraelem */
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
		}
	}
	
	/* free elements */
	BLI_freelistN(&ked.list);
	BLI_freelistN(&anim_data);
}
示例#12
0
/* Borderselect only selects keyframes now, as overshooting handles often get caught too,
 * which means that they may be inadvertently moved as well. However, incl_handles overrides
 * 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, const rctf *rectf_view, short mode, short selectmode, bool incl_handles,
        struct KeyframeEdit_LassoData *data_lasso)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter, mapping_flag;
	
	SpaceIpo *sipo = (SpaceIpo *)ac->sl;
	KeyframeEditData ked;
	KeyframeEditFunc ok_cb, select_cb;
	View2D *v2d = &ac->ar->v2d;
	rctf rectf, scaled_rectf;
	
	/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
	UI_view2d_region_to_view_rctf(v2d, rectf_view, &rectf);
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* get beztriple editing/validation funcs  */
	select_cb = ANIM_editkeyframes_select(selectmode);
	ok_cb = ANIM_editkeyframes_ok(mode);
	
	/* init editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));
	if (data_lasso) {
		data_lasso->rectf_scaled = &scaled_rectf;
		ked.data = data_lasso;
	}
	else {
		ked.data = &scaled_rectf;
	}
	
	/* treat handles separately? */
	if (incl_handles) {
		ked.iterflags |= KEYFRAME_ITER_INCL_HANDLES;
		mapping_flag = 0;
	}
	else
		mapping_flag = ANIM_UNITCONV_ONLYKEYS;

	mapping_flag |= ANIM_get_normalization_flags(ac);

	/* loop over data, doing border select */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		FCurve *fcu = (FCurve *)ale->key_data;
		float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);

		/* apply NLA mapping to all the keyframes, since it's easier than trying to
		 * guess when a callback might use something different
		 */
		if (adt)
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, incl_handles == 0);

		scaled_rectf.xmin = rectf.xmin;
		scaled_rectf.xmax = rectf.xmax;
		scaled_rectf.ymin = rectf.ymin / unit_scale;
		scaled_rectf.ymax = rectf.ymax / unit_scale;

		/* set horizontal range (if applicable) 
		 * NOTE: these values are only used for x-range and y-range but not region 
		 *      (which uses ked.data, i.e. rectf)
		 */
		if (mode != BEZT_OK_VALUERANGE) {
			ked.f1 = rectf.xmin;
			ked.f2 = rectf.xmax;
		}
		else {
			ked.f1 = rectf.ymin;
			ked.f2 = rectf.ymax;
		}
		
		/* firstly, check if any keyframes will be hit by this */
		if (ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, ok_cb, NULL)) {
			/* select keyframes that are in the appropriate places */
			ANIM_fcurve_keyframes_loop(&ked, fcu, ok_cb, select_cb, NULL);
			
			/* only change selection of channel when the visibility of keyframes doesn't depend on this */
			if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
				/* select the curve too now that curve will be touched */
				if (selectmode == SELECT_ADD)
					fcu->flag |= FCURVE_SELECTED;
			}
		}
		
		/* un-apply NLA mapping from all the keyframes */
		if (adt)
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, incl_handles == 0);
	}
	
	/* cleanup */
	BLI_freelistN(&anim_data);
}
示例#13
0
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short select_mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditFunc select_cb, ok_cb;
	KeyframeEditData ked;
	tNearestVertInfo *nvi;
	float selx = (float)ac->scene->r.cfra;
	
	/* find the beztriple that we're selecting, and the handle that was clicked on */
	nvi = find_nearest_fcurve_vert(ac, mval);
	
	/* check if anything to select */
	if (nvi == NULL)
		return;
	
	/* get frame number on which elements should be selected */
	// TODO: should we restrict to integer frames only?
	if (nvi->bezt)
		selx = nvi->bezt->vec[1][0];
	else if (nvi->fpt)
		selx = nvi->fpt->vec[0];
	
	/* if select mode is replace, deselect all keyframes first */
	if (select_mode == SELECT_REPLACE) {
		/* reset selection mode to add to selection */
		select_mode = SELECT_ADD;
		
		/* - 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
		 */
		deselect_graph_keys(ac, 0, SELECT_SUBTRACT, false);
	}
	
	/* initialize keyframe editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));
	
	/* set up BezTriple edit callbacks */
	select_cb = ANIM_editkeyframes_select(select_mode);
	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
	 */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		/* set frame for validation callback to refer to */
		if (adt)
			ked.f1 = BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
		else
			ked.f1 = selx;
		
		/* select elements with frame number matching cfra */
		ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
	}
	
	/* free elements */
	MEM_freeN(nvi);
	BLI_freelistN(&ked.list);
	BLI_freelistN(&anim_data);
}
示例#14
0
/* option 1) select keyframe directly under mouse */
static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_mode, short curves_only)
{
	SpaceIpo *sipo = (SpaceIpo *)ac->sl;
	tNearestVertInfo *nvi;
	BezTriple *bezt = NULL;
	
	/* find the beztriple that we're selecting, and the handle that was clicked on */
	nvi = find_nearest_fcurve_vert(ac, mval);
	
	/* check if anything to select */
	if (nvi == NULL)
		return;
	
	/* deselect all other curves? */
	if (select_mode == SELECT_REPLACE) {
		/* reset selection mode */
		select_mode = SELECT_ADD;
		
		/* deselect all other keyframes (+ F-Curves too) */
		deselect_graph_keys(ac, 0, SELECT_SUBTRACT, true);
		
		/* deselect other channels too, but only only do this if 
		 * selection of channel when the visibility of keyframes 
		 * doesn't depend on this 
		 */
		if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0)
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
	}
	
	/* if points can be selected on this F-Curve */
	// TODO: what about those with no keyframes?
	if ((curves_only == 0) && ((nvi->fcu->flag & FCURVE_PROTECTED) == 0)) {
		/* only if there's keyframe */
		if (nvi->bezt) {
			bezt = nvi->bezt; /* used to check bezt seletion is set */
			/* depends on selection mode */
			if (select_mode == SELECT_INVERT) {
				/* keyframe - invert select of all */
				if (nvi->hpoint == NEAREST_HANDLE_KEY) {
					if (BEZSELECTED(bezt)) {
						BEZ_DESEL(bezt);
					}
					else {
						BEZ_SEL(bezt);
					}
				}
				
				/* handles - toggle selection of relevant handle */
				else if (nvi->hpoint == 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 (nvi->hpoint == NEAREST_HANDLE_KEY) {
					BEZ_SEL(bezt);
				}
				/* otherwise, select the handle that applied */
				else if (nvi->hpoint == NEAREST_HANDLE_LEFT) 
					bezt->f1 |= SELECT;
				else 
					bezt->f3 |= SELECT;
			}
		}
		else if (nvi->fpt) {
			// TODO: need to handle sample points
		}
	}
	else {
		KeyframeEditFunc select_cb;
		KeyframeEditData ked;
		
		/* initialize keyframe editing data */
		memset(&ked, 0, sizeof(KeyframeEditData));
		
		/* set up BezTriple edit callbacks */
		select_cb = ANIM_editkeyframes_select(select_mode);
		
		/* select all keyframes */
		ANIM_fcurve_keyframes_loop(&ked, nvi->fcu, NULL, select_cb, NULL);
	}
	
	/* only change selection of channel when the visibility of keyframes doesn't depend on this */
	if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0) {
		/* select or deselect curve? */
		if (bezt) {
			/* take selection status from item that got hit, to prevent flip/flop on channel 
			 * selection status when shift-selecting (i.e. "SELECT_INVERT") points
			 */
			if (BEZSELECTED(bezt))
				nvi->fcu->flag |= FCURVE_SELECTED;
			else
				nvi->fcu->flag &= ~FCURVE_SELECTED;
		}
		else {
			/* didn't hit any channel, so just apply that selection mode to the curve's selection status */
			if (select_mode == SELECT_INVERT)
				nvi->fcu->flag ^= FCURVE_SELECTED;
			else if (select_mode == SELECT_ADD)
				nvi->fcu->flag |= FCURVE_SELECTED;
		}
	}

	/* set active F-Curve (NOTE: sync the filter flags with findnearest_fcurve_vert) */
	/* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) otherwise the active flag won't be set [#26452] */
	if (nvi->fcu->flag & FCURVE_SELECTED) {
		int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
		ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, ANIMTYPE_FCURVE);
	}

	/* free temp sample data for filtering */
	MEM_freeN(nvi);
}
示例#15
0
static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short selectmode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditData ked;
	KeyframeEditFunc ok_cb, select_cb;
	View2D *v2d= &ac->ar->v2d;
	rctf rectf;
	float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT_HALF);
	
	/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
	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 */
	filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* get beztriple editing/validation funcs  */
	select_cb= ANIM_editkeyframes_select(selectmode);
	
	if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS))
		ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
	else
		ok_cb= NULL;
		
	/* init editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));
	
	/* loop over data, doing border select */
	for (ale= anim_data.first; ale; ale= ale->next) {
		AnimData *adt= ANIM_nla_mapping_get(ac, ale);
		
		/* get new vertical minimum extent of channel */
		ymin= ymax - ACHANNEL_STEP;
		
		/* set horizontal range (if applicable) */
		if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
			/* if channel is mapped in NLA, apply correction */
			if (adt) {
				ked.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
				ked.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
			}
			else {
				ked.f1= rectf.xmin;
				ked.f2= rectf.xmax;
			}
		}
		
		/* perform vertical suitability check (if applicable) */
		if ( (mode == ACTKEYS_BORDERSEL_FRAMERANGE) || 
			!((ymax < rectf.ymin) || (ymin > rectf.ymax)) )
		{
			/* loop over data selecting */
			if (ale->type == ANIMTYPE_GPLAYER)
				borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
			else
				ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
		}
		
		/* set minimum extent to be the maximum of the next channel */
		ymax=ymin;
	}
	
	/* cleanup */
	BLI_freelistN(&anim_data);
}
示例#16
0
static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditData ked;
	KeyframeEditFunc ok_cb, select_cb;
	View2D *v2d = &ac->ar->v2d;
	rctf rectf;
	float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));
	
	/* convert mouse coordinates to frame ranges and channel coordinates corrected for view pan/zoom */
	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 */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* get beztriple editing/validation funcs  */
	select_cb = ANIM_editkeyframes_select(selectmode);
	
	if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS))
		ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
	else
		ok_cb = NULL;
		
	/* init editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));
	
	/* loop over data, doing border select */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		/* get new vertical minimum extent of channel */
		ymin = ymax - ACHANNEL_STEP(ac);
		
		/* set horizontal range (if applicable) */
		if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
			/* if channel is mapped in NLA, apply correction */
			if (adt) {
				ked.iterflags &= ~(KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP);
				ked.f1 = BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
				ked.f2 = BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
			}
			else {
				ked.iterflags |= (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP); /* for summary tracks */
				ked.f1 = rectf.xmin;
				ked.f2 = rectf.xmax;
			}
		}
		
		/* perform vertical suitability check (if applicable) */
		if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) ||
		    !((ymax < rectf.ymin) || (ymin > rectf.ymax)))
		{
			/* loop over data selecting */
			switch (ale->type) {
#if 0 /* XXX: Keyframes are not currently shown here */
				case ANIMTYPE_GPDATABLOCK:
				{
					bGPdata *gpd = ale->data;
					bGPDlayer *gpl;
					for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
						ED_gplayer_frames_select_border(gpl, rectf.xmin, rectf.xmax, selectmode);
					}
					break;
				}
#endif
				case ANIMTYPE_GPLAYER:
					ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
					break;
				case ANIMTYPE_MASKDATABLOCK:
				{
					Mask *mask = ale->data;
					MaskLayer *masklay;
					for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
						ED_masklayer_frames_select_border(masklay, rectf.xmin, rectf.xmax, selectmode);
					}
					break;
				}
				case ANIMTYPE_MASKLAYER:
					ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
					break;
				default:
					ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
					break;
			}
		}
		
		/* set minimum extent to be the maximum of the next channel */
		ymax = ymin;
	}
	
	/* cleanup */
	ANIM_animdata_freelist(&anim_data);
}
示例#17
0
static void actkeys_select_leftright(bAnimContext *ac, short leftright, short select_mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditFunc ok_cb, select_cb;
	KeyframeEditData ked = {{NULL}};
	Scene *scene = ac->scene;
	
	/* if select mode is replace, deselect all keyframes (and channels) first */
	if (select_mode == SELECT_REPLACE) {
		select_mode = SELECT_ADD;
		
		/* - 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
		 */
		deselect_action_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);
	
	if (leftright == ACTKEYS_LRSEL_LEFT) {
		ked.f1 = MINAFRAMEF;
		ked.f2 = (float)(CFRA + 0.1f);
	}
	else {
		ked.f1 = (float)(CFRA - 0.1f);
		ked.f2 = MAXFRAMEF;
	}
	
	/* filter data */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
		
	/* select keys */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		if (adt) {
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
		}
		else if (ale->type == ANIMTYPE_GPLAYER)
			ED_gplayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode);
		else if (ale->type == ANIMTYPE_MASKLAYER)
			ED_masklayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode);
		else
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
	}
	
	/* Sync marker support */
	if (select_mode == SELECT_ADD) {
		SpaceAction *saction = (SpaceAction *)ac->sl;
		
		if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) {
			ListBase *markers = ED_animcontext_get_markers(ac);
			TimeMarker *marker;
			
			for (marker = markers->first; marker; marker = marker->next) {
				if (((leftright == ACTKEYS_LRSEL_LEFT)  && (marker->frame <  CFRA)) ||
				    ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA)))
				{
					marker->flag |= SELECT;
				}
				else {
					marker->flag &= ~SELECT;
				}
			}
		}
	}

	/* Cleanup */
	ANIM_animdata_freelist(&anim_data);
}
示例#18
0
/* Option 3) Selects all visible keyframes in the same frame as the mouse click */
static void graphkeys_mselect_column (bAnimContext *ac, int mval[2], short select_mode)
{
	ListBase anim_data= {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
	KeyframeEditFunc select_cb, ok_cb;
	KeyframeEditData ked;
	tNearestVertInfo *nvi;
	float selx = (float)ac->scene->r.cfra;
	
	/* find the beztriple that we're selecting, and the handle that was clicked on */
	nvi = find_nearest_fcurve_vert(ac, mval);
	
	/* check if anything to select */
	if (nvi == NULL)	
		return;
	
	/* get frame number on which elements should be selected */
	// TODO: should we restrict to integer frames only?
	if (nvi->bezt)
		selx= nvi->bezt->vec[1][0];
	else if (nvi->fpt)
		selx= nvi->fpt->vec[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 keyframes */
		deselect_graph_keys(ac, 0, SELECT_SUBTRACT);
		
		/* deselect other channels too, but only only do this if 
		 * selection of channel when the visibility of keyframes 
		 * doesn't depend on this 
		 */
		if ((sipo->flag & SIPO_SELCUVERTSONLY) == 0)
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
	}
	
	/* initialise keyframe editing data */
	memset(&ked, 0, sizeof(KeyframeEditData));
	
	/* set up BezTriple edit callbacks */
	select_cb= ANIM_editkeyframes_select(select_mode);
	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
	 */
	filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	for (ale= anim_data.first; ale; ale= ale->next) {
		AnimData *adt= ANIM_nla_mapping_get(ac, ale);
		
		/* set frame for validation callback to refer to */
		if (adt)
			ked.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
		else
			ked.f1= selx;
		
		/* select elements with frame number matching cfra */
		ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
	}
	
	/* free elements */
	MEM_freeN(nvi);
	BLI_freelistN(&ked.list);
	BLI_freelistN(&anim_data);
}