示例#1
0
static void duplicate_action_keys(bAnimContext *ac)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	/* filter data */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop through filtered data and delete selected keys */
	for (ale = anim_data.first; ale; ale = ale->next) {
		if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE))
			duplicate_fcurve_keys((FCurve *)ale->key_data);
		else if (ale->type == ANIMTYPE_GPLAYER)
			ED_gplayer_frames_duplicate((bGPDlayer *)ale->data);
		else if (ale->type == ANIMTYPE_MASKLAYER)
			ED_masklayer_frames_duplicate((MaskLayer *)ale->data);
		else
			BLI_assert(0);

		ale->update |= ANIM_UPDATE_DEFAULT;
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#2
0
/* this function is responsible for setting handle-type of selected keyframes */
static void sethandles_action_keys(bAnimContext *ac, short mode) 
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles(mode);
	KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop through setting flags for handles 
	 * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here...
	 */
	for (ale = anim_data.first; ale; ale = ale->next) {
		FCurve *fcu = (FCurve *)ale->key_data;
		
		/* any selected keyframes for editing? */
		if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) {
			/* change type of selected handles */
			ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, edit_cb, calchandles_fcurve);

			ale->update |= ANIM_UPDATE_DEFAULT;
		}
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#3
0
/* this function is responsible for mirroring keyframes */
static void mirror_action_keys(bAnimContext *ac, short mode) 
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditData ked = {{NULL}};
	KeyframeEditFunc edit_cb;
	
	/* get beztriple editing callbacks */
	edit_cb = ANIM_editkeyframes_mirror(mode);

	ked.scene = ac->scene;
	
	/* for 'first selected marker' mode, need to find first selected marker first! */
	/* XXX should this be made into a helper func in the API? */
	if (mode == ACTKEYS_MIRROR_MARKER) {
		TimeMarker *marker = ED_markers_get_first_selected(ac->markers);
		
		if (marker)
			ked.f1 = (float)marker->frame;
		else
			return;
	}
	
	/* filter data */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* mirror keyframes */
	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, NULL, edit_cb, calchandles_fcurve);
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
		}
		//else if (ale->type == ACTTYPE_GPLAYER)
		//	snap_gplayer_frames(ale->data, mode);
		else 
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);

		ale->update |= ANIM_UPDATE_DEFAULT;
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#4
0
/* this function is responsible for snapping keyframes to frame-times */
static void snap_action_keys(bAnimContext *ac, short mode) 
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	KeyframeEditData ked = {{NULL}};
	KeyframeEditFunc edit_cb;
	
	/* filter data */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* get beztriple editing callbacks */
	edit_cb = ANIM_editkeyframes_snap(mode);

	ked.scene = ac->scene;
	if (mode == ACTKEYS_SNAP_NEAREST_MARKER) {
		ked.list.first = (ac->markers) ? ac->markers->first : NULL;
		ked.list.last = (ac->markers) ? ac->markers->last : NULL;
	}
	
	/* snap keyframes */
	for (ale = anim_data.first; ale; ale = ale->next) {
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		
		if (ale->type == ANIMTYPE_GPLAYER) {
			ED_gplayer_snap_frames(ale->data, ac->scene, mode);
		}
		else if (ale->type == ANIMTYPE_MASKLAYER) {
			ED_masklayer_snap_frames(ale->data, ac->scene, mode);
		}
		else if (adt) {
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
			ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
		}
		else {
			ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
		}

		ale->update |= ANIM_UPDATE_DEFAULT;
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#5
0
static bool delete_action_keys(bAnimContext *ac)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	bool changed_final = false;

	/* filter data */
	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
	else
		filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);

	/* loop through filtered data and delete selected keys */
	for (ale = anim_data.first; ale; ale = ale->next) {
		bool changed = false;

		if (ale->type == ANIMTYPE_GPLAYER) {
			changed = ED_gplayer_frames_delete((bGPDlayer *)ale->data);
		}
		else if (ale->type == ANIMTYPE_MASKLAYER) {
			changed = ED_masklayer_frames_delete((MaskLayer *)ale->data);
		}
		else {
			FCurve *fcu = (FCurve *)ale->key_data;
			AnimData *adt = ale->adt;
			
			/* delete selected keyframes only */
			changed = delete_fcurve_keys(fcu);
			
			/* Only delete curve too if it won't be doing anything anymore */
			if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) {
				ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
				ale->key_data = NULL;
			}
		}

		if (changed) {
			ale->update |= ANIM_UPDATE_DEFAULT;
			changed_final = true;
		}
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);

	return changed_final;
}
示例#6
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);
}
示例#7
0
/* this function is responsible for setting extrapolation mode for keyframes */
static void setexpo_action_keys(bAnimContext *ac, short mode) 
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop through setting mode per F-Curve */
	for (ale = anim_data.first; ale; ale = ale->next) {
		FCurve *fcu = (FCurve *)ale->data;
		
		if (mode >= 0) {
			/* just set mode setting */
			fcu->extend = mode;
		}
		else {
			/* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation 
			 * without having to go through FModifier UI in Graph Editor to do so
			 */
			if (mode == MAKE_CYCLIC_EXPO) {
				/* only add if one doesn't exist */
				if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) {
					/* TODO: add some more preset versions which set different extrapolation options? */
					add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES);
				}
			}
			else if (mode == CLEAR_CYCLIC_EXPO) {
				/* remove all the modifiers fitting this description */
				FModifier *fcm, *fcn = NULL;
				
				for (fcm = fcu->modifiers.first; fcm; fcm = fcn) {
					fcn = fcm->next;
					
					if (fcm->type == FMODIFIER_TYPE_CYCLES)
						remove_fmodifier(&fcu->modifiers, fcm);
				}
			}
		}

		ale->update |= ANIM_UPDATE_DEFAULT;
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#8
0
/* Evaluates the curves between each selected keyframe on each frame, and keys the value  */
static void sample_action_keys(bAnimContext *ac)
{	
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop through filtered data and add keys between selected keyframes on every frame  */
	for (ale = anim_data.first; ale; ale = ale->next) {
		sample_fcurve((FCurve *)ale->key_data);

		ale->update |= ANIM_UPDATE_DEPS;
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#9
0
static void clean_action_keys(bAnimContext *ac, float thresh, bool clean_chan)
{	
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop through filtered data and clean curves */
	for (ale = anim_data.first; ale; ale = ale->next) {
		clean_fcurve(ac, ale, thresh, clean_chan);

		ale->update |= ANIM_UPDATE_DEFAULT;
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#10
0
/* this function is responsible for setting the keyframe type for Grease Pencil frames */
static void setkeytype_gpencil_keys(bAnimContext *ac, short mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop through each layer */
	for (ale = anim_data.first; ale; ale = ale->next) {
		if (ale->type == ANIMTYPE_GPLAYER) {
			ED_gplayer_frames_keytype_set(ale->data, mode);
			ale->update |= ANIM_UPDATE_DEPS;
		}
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#11
0
/* this function is responsible for setting keyframe type for keyframes */
static void setkeytype_action_keys(bAnimContext *ac, short mode) 
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	KeyframeEditFunc set_cb = ANIM_editkeyframes_keytype(mode);
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop through setting BezTriple interpolation
	 * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here...
	 */
	for (ale = anim_data.first; ale; ale = ale->next) {
		ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, NULL);

		ale->update |= ANIM_UPDATE_DEPS | ANIM_UPDATE_HANDLES;
	}

	ANIM_animdata_update(ac, &anim_data);
	ANIM_animdata_freelist(&anim_data);
}
示例#12
0
/**
 * This function pastes data from the keyframes copy/paste buffer
 *
 * \return Status code is whether the method FAILED to do anything
 */
short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
                          const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode, bool flip)
{
	bAnimListElem *ale;
	
	const Scene *scene = (ac->scene);
	
	const bool from_single = BLI_listbase_is_single(&animcopybuf);
	const bool to_simple = BLI_listbase_is_single(anim_data);
	
	float offset = 0.0f;
	int pass;

	/* check if buffer is empty */
	if (BLI_listbase_is_empty(&animcopybuf)) {
		BKE_report(ac->reports, RPT_ERROR, "No animation data in buffer to paste");
		return -1;
	}

	if (BLI_listbase_is_empty(anim_data)) {
		BKE_report(ac->reports, RPT_ERROR, "No selected F-Curves to paste into");
		return -1;
	}
	
	/* methods of offset */
	switch (offset_mode) {
		case KEYFRAME_PASTE_OFFSET_CFRA_START:
			offset = (float)(CFRA - animcopy_firstframe);
			break;
		case KEYFRAME_PASTE_OFFSET_CFRA_END:
			offset = (float)(CFRA - animcopy_lastframe);
			break;
		case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
			offset = (float)(CFRA - animcopy_cfra);
			break;
		case KEYFRAME_PASTE_OFFSET_NONE:
			offset = 0.0f;
			break;
	}

	if (from_single && to_simple) {
		/* 1:1 match, no tricky checking, just paste */
		FCurve *fcu;
		tAnimCopybufItem *aci;
		
		ale = anim_data->first;
		fcu = (FCurve *)ale->data;  /* destination F-Curve */
		aci = animcopybuf.first;
		
		paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false);
		ale->update |= ANIM_UPDATE_DEFAULT;
	}
	else {
		/* from selected channels 
		 *  This "passes" system aims to try to find "matching" channels to paste keyframes
		 *  into with increasingly loose matching heuristics. The process finishes when at least
		 *  one F-Curve has been pasted into.
		 */
		for (pass = 0; pass < 3; pass++) {
			unsigned int totmatch = 0;
			
			for (ale = anim_data->first; ale; ale = ale->next) {
				/* find buffer item to paste from 
				 *	- if names don't matter (i.e. only 1 channel in buffer), don't check id/group
				 *	- if names do matter, only check if id-type is ok for now (group check is not that important)
				 *	- most importantly, rna-paths should match (array indices are unimportant for now)
				 */
				AnimData *adt = ANIM_nla_mapping_get(ac, ale);
				FCurve *fcu = (FCurve *)ale->data;  /* destination F-Curve */
				tAnimCopybufItem *aci = NULL;
				
				switch (pass) {
					case 0:
						/* most strict, must be exact path match data_path & index */
						aci = pastebuf_match_path_full(fcu, from_single, to_simple, flip);
						break;
					
					case 1:
						/* less strict, just compare property names */
						aci = pastebuf_match_path_property(fcu, from_single, to_simple);
						break;
					
					case 2:
						/* Comparing properties gave no results, so just do index comparisons */
						aci = pastebuf_match_index_only(fcu, from_single, to_simple);
						break;
				}
				
				/* copy the relevant data from the matching buffer curve */
				if (aci) {
					totmatch++;
					
					if (adt) {
						ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
						paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
						ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
					}
					else {
						paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, flip);
					}
				}
				
				ale->update |= ANIM_UPDATE_DEFAULT;
			}
			
			/* don't continue if some fcurves were pasted */
			if (totmatch)
				break;
		}
	}
	
	ANIM_animdata_update(ac, anim_data);

	return 0;
}