示例#1
0
/* Get the min/max keyframes*/
static void get_keyframe_extents (bAnimContext *ac, float *min, float *max, const short onlySel)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	/* get data to filter, from Action or Dopesheet */
	filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* set large values to try to override */
	*min= 999999999.0f;
	*max= -999999999.0f;
	
	/* check if any channels to set range with */
	if (anim_data.first) {
		/* go through channels, finding max extents */
		for (ale= anim_data.first; ale; ale= ale->next) {
			AnimData *adt= ANIM_nla_mapping_get(ac, ale);
			FCurve *fcu= (FCurve *)ale->key_data;
			float tmin, tmax;
			
			/* get range and apply necessary scaling before processing */
			calc_fcurve_range(fcu, &tmin, &tmax, onlySel);
			
			if (adt) {
				tmin= BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
				tmax= BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP);
			}
			
			/* try to set cur using these values, if they're more extreme than previously set values */
			*min= MIN2(*min, tmin);
			*max= MAX2(*max, tmax);
		}
		
		/* free memory */
		BLI_freelistN(&anim_data);
	}
	else {
		/* set default range */
		if (ac->scene) {
			*min= (float)ac->scene->r.sfra;
			*max= (float)ac->scene->r.efra;
		}
		else {
			*min= -5;
			*max= 100;
		}
	}
}
示例#2
0
void ui_but_anim_flag(uiBut *but, float cfra)
{
	AnimData *adt;
	bAction *act;
	FCurve *fcu;
	bool driven;

	but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN);

	fcu = ui_but_get_fcurve(but, &adt, &act, &driven);

	if (fcu) {
		if (!driven) {
			but->flag |= UI_BUT_ANIMATED;
			
			/* T41525 - When the active action is a NLA strip being edited, 
			 * we need to correct the frame number to "look inside" the
			 * remapped action
			 */
			if (adt)
				cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
			
			if (fcurve_frame_has_keyframe(fcu, cfra, 0))
				but->flag |= UI_BUT_ANIMATED_KEY;
		}
		else {
			but->flag |= UI_BUT_DRIVEN;
		}
	}
}
示例#3
0
void ui_but_anim_flag(uiBut *but, float cfra)
{
	AnimData *adt;
	bAction *act;
	FCurve *fcu;
	bool driven;
	bool special;
	
	but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN);
	
	/* NOTE: "special" is reserved for special F-Curves stored on the animation data
	 *        itself (which are used to animate properties of the animation data).
	 *        We count those as "animated" too for now
	 */
	fcu = ui_but_get_fcurve(but, &adt, &act, &driven, &special);
	
	if (fcu) {
		if (!driven) {
			but->flag |= UI_BUT_ANIMATED;
			
			/* T41525 - When the active action is a NLA strip being edited, 
			 * we need to correct the frame number to "look inside" the
			 * remapped action
			 */
			if (adt)
				cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
			
			if (fcurve_frame_has_keyframe(fcu, cfra, 0))
				but->flag |= UI_BUT_ANIMATED_KEY;
		}
		else {
			but->flag |= UI_BUT_DRIVEN;
		}
	}
}
示例#4
0
/* helper function for ANIM_nla_mapping_apply_fcurve() -> "apply", i.e. mapping points to NLA-mapped global time */
static short bezt_nlamapping_apply(KeyframeEditData *ked, BezTriple *bezt)
{
	/* AnimData block providing scaling is stored in 'data', only_keys option is stored in i1 */
	AnimData *adt = (AnimData *)ked->data;
	short only_keys = (short)ked->i1;
	
	/* adjust BezTriple handles only if allowed to */
	if (only_keys == 0) {
		bezt->vec[0][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[0][0], NLATIME_CONVERT_MAP);
		bezt->vec[2][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[2][0], NLATIME_CONVERT_MAP);
	}
	
	bezt->vec[1][0] = BKE_nla_tweakedit_remap(adt, bezt->vec[1][0], NLATIME_CONVERT_MAP);
	
	return 0;
}
示例#5
0
/* this function is responsible for snapping keyframes to frame-times */
static void insert_action_keys(bAnimContext *ac, short mode) 
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	ReportList *reports = ac->reports;
	Scene *scene = ac->scene;
	short flag = 0;
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	if (mode == 2) filter |= ANIMFILTER_SEL;
	else if (mode == 3) filter |= ANIMFILTER_ACTGROUPED;
	
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* init keyframing flag */
	flag = ANIM_get_keyframing_flags(scene, 1);
	
	/* insert keyframes */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		FCurve *fcu = (FCurve *)ale->key_data;
		float cfra;
		
		/* adjust current frame for NLA-scaling */
		if (adt)
			cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
		else 
			cfra = (float)CFRA;
			
		/* read value from property the F-Curve represents, or from the curve only?
		 * - ale->id != NULL:    Typically, this means that we have enough info to try resolving the path
		 * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
		 *                       so it's easier for now to just read the F-Curve directly.
		 *                       (TODO: add the full-blown PointerRNA relative parsing case here...)
		 */
		if (ale->id && !ale->owner)
			insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
		else
			insert_vert_fcurve(fcu, cfra, fcu->curval, 0);

		ale->update |= ANIM_UPDATE_DEFAULT;
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#6
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);
}
示例#7
0
文件: action_edit.c 项目: jinjoh/NOOR
/* this function is responsible for snapping keyframes to frame-times */
static void insert_action_keys(bAnimContext *ac, short mode) 
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	Scene *scene= ac->scene;
	float cfra= (float)CFRA;
	short flag = 0;
	
	/* filter data */
	filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
	if (mode == 2) 			filter |= ANIMFILTER_SEL;
	else if (mode == 3) 	filter |= ANIMFILTER_ACTGROUPED;
	
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* init keyframing flag */
	if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
	if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
	if (IS_AUTOKEY_MODE(scene, EDITKEYS)) flag |= INSERTKEY_REPLACE;
	
	/* insert keyframes */
	for (ale= anim_data.first; ale; ale= ale->next) {
		AnimData *adt= ANIM_nla_mapping_get(ac, ale);
		FCurve *fcu= (FCurve *)ale->key_data;
		
		/* adjust current frame for NLA-scaling */
		if (adt)
			cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
		else 
			cfra= (float)CFRA;
			
		/* if there's an id */
		if (ale->id)
			insert_keyframe(ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
		else
			insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
	}
	
	BLI_freelistN(&anim_data);
}
示例#8
0
/* this function is responsible for snapping keyframes to frame-times */
static void insert_action_keys(bAnimContext *ac, short mode) 
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	ReportList *reports = ac->reports;
	Scene *scene = ac->scene;
	short flag = 0;
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	if (mode == 2) filter |= ANIMFILTER_SEL;
	else if (mode == 3) filter |= ANIMFILTER_ACTGROUPED;
	
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* init keyframing flag */
	flag = ANIM_get_keyframing_flags(scene, 1);
	
	/* insert keyframes */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		FCurve *fcu = (FCurve *)ale->key_data;
		float cfra;
		
		/* adjust current frame for NLA-scaling */
		if (adt)
			cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
		else 
			cfra = (float)CFRA;
			
		/* if there's an id */
		if (ale->id)
			insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
		else
			insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
	}
	
	BLI_freelistN(&anim_data);
}
示例#9
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);
}
示例#10
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);
}
示例#11
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);
}
示例#12
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);
}
示例#13
0
static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_mode, bool column, bool same_channel)
{
	ListBase anim_data = {NULL, NULL};
	DLRBT_Tree anim_keys;
	bAnimListElem *ale;
	int filter;
	
	View2D *v2d = &ac->ar->v2d;
	bDopeSheet *ads = NULL;
	int channel_index;
	bool found = false;
	float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
	float selx = 0.0f;  /* frame of keyframe under mouse */
	float key_hsize;
	float x, y;
	rctf rectf;
	
	/* get dopesheet info */
	if (ac->datatype == ANIMCONT_DOPESHEET)
		ads = ac->data;
	
	/* 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, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
	
	/* x-range to check is +/- 7px for standard keyframe under standard dpi/y-scale (in screen/region-space),
	 * on either side of mouse click (size of keyframe icon)
	 */
	key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;    /* standard channel height (to allow for some slop) */
	key_hsize = roundf(key_hsize / 2.0f);      /* half-size (for either side), but rounded up to nearest int (for easier targetting) */
	
	UI_view2d_region_to_view(v2d, mval[0] - (int)key_hsize, mval[1], &rectf.xmin, &rectf.ymin);
	UI_view2d_region_to_view(v2d, mval[0] + (int)key_hsize, mval[1], &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);
	
	/* try to get channel */
	ale = BLI_findlink(&anim_data, channel_index);
	if (ale == NULL) {
		/* channel not found */
		printf("Error: animation channel (index = %d) not found in mouse_action_keys()\n", channel_index);
		ANIM_animdata_freelist(&anim_data);
		return;
	}
	else {
		/* found match - must return here... */
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		ActKeyColumn *ak, *akn = NULL;
		
		/* make list of keyframes */
		BLI_dlrbTree_init(&anim_keys);
		
		if (ale->key_data) {
			switch (ale->datatype) {
				case ALE_SCE:
				{
					Scene *scene = (Scene *)ale->key_data;
					scene_to_keylist(ads, scene, &anim_keys, NULL);
					break;
				}
				case ALE_OB:
				{
					Object *ob = (Object *)ale->key_data;
					ob_to_keylist(ads, ob, &anim_keys, NULL);
					break;
				}
				case ALE_ACT:
				{
					bAction *act = (bAction *)ale->key_data;
					action_to_keylist(adt, act, &anim_keys, NULL);
					break;
				}
				case ALE_FCURVE:
				{
					FCurve *fcu = (FCurve *)ale->key_data;
					fcurve_to_keylist(adt, fcu, &anim_keys, NULL);
					break;
				}
			}
		}
		else if (ale->type == ANIMTYPE_SUMMARY) {
			/* dopesheet summary covers everything */
			summary_to_keylist(ac, &anim_keys, NULL);
		}
		else if (ale->type == ANIMTYPE_GROUP) {
			// TODO: why don't we just give groups key_data too?
			bActionGroup *agrp = (bActionGroup *)ale->data;
			agroup_to_keylist(adt, agrp, &anim_keys, NULL);
		}
		else if (ale->type == ANIMTYPE_GPLAYER) {
			// TODO: why don't we just give gplayers key_data too?
			bGPDlayer *gpl = (bGPDlayer *)ale->data;
			gpl_to_keylist(ads, gpl, &anim_keys);
		}
		else if (ale->type == ANIMTYPE_MASKLAYER) {
			// TODO: why don't we just give masklayers key_data too?
			MaskLayer *masklay = (MaskLayer *)ale->data;
			mask_to_keylist(ads, masklay, &anim_keys);
		}

		/* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */
		for (ak = anim_keys.root; ak; ak = akn) {
			if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) {
				/* set the frame to use, and apply inverse-correction for NLA-mapping 
				 * so that the frame will get selected by the selection functions without
				 * requiring to map each frame once again...
				 */
				selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
				frame = ak->cfra;
				found = true;
				break;
			}
			else if (ak->cfra < rectf.xmin)
				akn = ak->right;
			else
				akn = ak->left;
		}
		
		/* remove active channel from list of channels for separate treatment (since it's needed later on) */
		BLI_remlink(&anim_data, ale);
		
		/* cleanup temporary lists */
		BLI_dlrbTree_free(&anim_keys);
		
		/* free list of channels, since it's not used anymore */
		ANIM_animdata_freelist(&anim_data);
	}
	
	/* 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 keyframes */
		deselect_action_keys(ac, 0, SELECT_SUBTRACT);
		
		/* highlight channel clicked on */
		if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
			
			/* Highlight Action-Group or F-Curve? */
			if (ale && ale->data) {
				if (ale->type == ANIMTYPE_GROUP) {
					bActionGroup *agrp = ale->data;
					
					agrp->flag |= AGRP_SELECTED;
					ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
				}
				else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
					FCurve *fcu = ale->data;
					
					fcu->flag |= FCURVE_SELECTED;
					ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
				}
			}
		}
		else if (ac->datatype == ANIMCONT_GPENCIL) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
			
			/* Highlight GPencil Layer */
			if ((ale && ale->data) && (ale->type == ANIMTYPE_GPLAYER)) {
				bGPDlayer *gpl = ale->data;
				
				gpl->flag |= GP_LAYER_SELECT;
				//gpencil_layer_setactive(gpd, gpl);
			}
		}
		else if (ac->datatype == ANIMCONT_MASK) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);

			/* Highlight GPencil Layer */
			if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) {
				MaskLayer *masklay = ale->data;

				masklay->flag |= MASK_LAYERFLAG_SELECT;
				//gpencil_layer_setactive(gpd, gpl);
			}
		}
	}
	
	/* only select keyframes if we clicked on a valid channel and hit something */
	if (ale) {
		if (found) {
			/* apply selection to keyframes */
			if (column) {
				/* select all keyframes in the same frame as the one we hit on the active channel 
				 * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
				 *            does that itself again as it needs to work on multiple datablocks 
				 */
				actkeys_mselect_column(ac, select_mode, frame);
			}
			else if (same_channel) {
				/* select all keyframes in the active channel */
				actkeys_mselect_channel_only(ac, ale, select_mode);	
			}
			else {
				/* select the nominated keyframe on the given frame */
				actkeys_mselect_single(ac, ale, select_mode, selx);
			}
		}
		
		/* free this channel */
		MEM_freeN(ale);
	}
}
示例#14
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);
}
示例#15
0
/* This function is used to loop over the keyframe data in a DopeSheet summary */
static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter, ret_code = 0;
	
	/* sanity check */
	if (ac == NULL)
		return 0;
	
	/* get F-Curves to take keyframes from */
	filter = ANIMFILTER_DATA_VISIBLE;
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop through each F-Curve, working on the keyframes until the first curve aborts */
	for (ale = anim_data.first; ale; ale = ale->next) {
		switch (ale->datatype) {
			case ALE_MASKLAY:
			case ALE_GPFRAME:
				break;
				
			case ALE_FCURVE:
			default:
			{
				if (ked && ked->iterflags) {
					/* make backups of the current values, so that a localised fix
					 * (e.g. NLA time remapping) can be applied to these values
					 */
					float f1 = ked->f1;
					float f2 = ked->f2;
					
					if (ked->iterflags & (KED_F1_NLA_UNMAP | KED_F2_NLA_UNMAP)) {
						AnimData *adt = ANIM_nla_mapping_get(ac, ale);
						
						if (ked->iterflags & KED_F1_NLA_UNMAP)
							ked->f1 = BKE_nla_tweakedit_remap(adt, f1, NLATIME_CONVERT_UNMAP);
						if (ked->iterflags & KED_F2_NLA_UNMAP)
							ked->f2 = BKE_nla_tweakedit_remap(adt, f2, NLATIME_CONVERT_UNMAP);
					}
					
					/* now operate on the channel as per normal */
					ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
					
					/* reset */
					ked->f1 = f1;
					ked->f2 = f2;
				}
				else {
					/* no special handling required... */
					ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
				}
				break;
			}
		}
		
		if (ret_code)
			break;
	}
	
	ANIM_animdata_freelist(&anim_data);
	
	return ret_code;
}
示例#16
0
/* Get the min/max keyframes*/
static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const short onlySel)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	bool found = false;
	
	/* get data to filter, from Action or Dopesheet */
	/* XXX: what is sel doing here?!
	 *      Commented it, was breaking things (eg. the "auto preview range" tool). */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL *//*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* set large values to try to override */
	*min = 999999999.0f;
	*max = -999999999.0f;
	
	/* check if any channels to set range with */
	if (anim_data.first) {
		/* go through channels, finding max extents */
		for (ale = anim_data.first; ale; ale = ale->next) {
			AnimData *adt = ANIM_nla_mapping_get(ac, ale);
			if (ale->datatype == ALE_GPFRAME) {
				bGPDlayer *gpl = ale->data;
				bGPDframe *gpf;

				/* find gp-frame which is less than or equal to cframe */
				for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
					const float framenum = (float)gpf->framenum;
					*min = min_ff(*min, framenum);
					*max = max_ff(*max, framenum);
					found = true;
				}
			}
			else if (ale->datatype == ALE_MASKLAY) {
				MaskLayer *masklay = ale->data;
				MaskLayerShape *masklay_shape;

				/* find mask layer which is less than or equal to cframe */
				for (masklay_shape = masklay->splines_shapes.first;
				     masklay_shape;
				     masklay_shape = masklay_shape->next)
				{
					const float framenum = (float)masklay_shape->frame;
					*min = min_ff(*min, framenum);
					*max = max_ff(*max, framenum);
					found = true;
				}
			}
			else {
				FCurve *fcu = (FCurve *)ale->key_data;
				float tmin, tmax;

				/* get range and apply necessary scaling before processing */
				if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, TRUE)) {

					if (adt) {
						tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
						tmax = BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP);
					}

					/* try to set cur using these values, if they're more extreme than previously set values */
					*min = min_ff(*min, tmin);
					*max = max_ff(*max, tmax);
					found = true;
				}
			}
		}
		
		/* free memory */
		BLI_freelistN(&anim_data);
	}
	else {
		/* set default range */
		if (ac->scene) {
			*min = (float)ac->scene->r.sfra;
			*max = (float)ac->scene->r.efra;
		}
		else {
			*min = -5;
			*max = 100;
		}
	}

	return found;
}
示例#17
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);
}