Esempio n. 1
0
/* Evaluates the curves between each selected keyframe on each frame, and keys the value  */
void sample_fcurve (FCurve *fcu)
{
	BezTriple *bezt, *start=NULL, *end=NULL;
	tempFrameValCache *value_cache, *fp;
	int sfra, range;
	int i, n, nIndex;
	
	/* find selected keyframes... once pair has been found, add keyframes  */
	for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
		/* check if selected, and which end this is */
		if (BEZSELECTED(bezt)) {
			if (start) {
				/* set end */
				end= bezt;
				
				/* cache values then add keyframes using these values, as adding
				 * keyframes while sampling will affect the outcome...
				 *	- only start sampling+adding from index=1, so that we don't overwrite original keyframe
				 */
				range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) );
				sfra= (int)( floor(start->vec[1][0]) );
				
				if (range) {
					value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache");
					
					/* 	sample values 	*/
					for (n=1, fp=value_cache; n<range && fp; n++, fp++) {
						fp->frame= (float)(sfra + n);
						fp->val= evaluate_fcurve(fcu, fp->frame);
					}
					
					/* 	add keyframes with these, tagging as 'breakdowns' 	*/
					for (n=1, fp=value_cache; n<range && fp; n++, fp++) {
						nIndex= insert_vert_fcurve(fcu, fp->frame, fp->val, 1);
						BEZKEYTYPE(fcu->bezt + nIndex)= BEZT_KEYTYPE_BREAKDOWN;
					}
					
					/* free temp cache */
					MEM_freeN(value_cache);
					
					/* as we added keyframes, we need to compensate so that bezt is at the right place */
					bezt = fcu->bezt + i + range - 1;
					i += (range - 1);
				}
				
				/* bezt was selected, so it now marks the start of a whole new chain to search */
				start= bezt;
				end= NULL;
			}
			else {
				/* just set start keyframe */
				start= bezt;
				end= NULL;
			}
		}
	}
	
	/* recalculate channel's handles? */
	calchandles_fcurve(fcu);
}
Esempio n. 2
0
/* Add the given BezTriple to the given 'list' of Keyframes */
static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt)
{
	ActKeyColumn *new_ak=NULL;
	
	if ELEM(NULL, keys, bezt) return;
	
	/* if there are no keys already, just add as root */
	if (keys->root == NULL) {
		/* just add this as the root, then call the tree-balancing functions to validate */
		new_ak= bezt_to_new_actkeycolumn(bezt);
		keys->root= (DLRBT_Node *)new_ak;
	}
	else {
		ActKeyColumn *ak, *akp=NULL, *akn=NULL;
		
		/* traverse tree to find an existing entry to update the status of, 
		 * or a suitable point to add at
		 */
		for (ak= keys->root; ak; akp= ak, ak= akn) {
			/* check if this is a match, or whether we go left or right */
			if (ak->cfra == bezt->vec[1][0]) {
				/* set selection status and 'touched' status */
				if (BEZSELECTED(bezt)) ak->sel = SELECT;
				ak->modified += 1;
				
				/* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
				if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
					ak->key_type= BEZT_KEYTYPE_KEYFRAME;
				
				/* done... no need to insert */
				return;
			}
			else {
				ActKeyColumn **aknp= NULL; 
				
				/* check if go left or right, but if not available, add new node */
				if (ak->cfra < bezt->vec[1][0]) 
					aknp= &ak->right;
				else
					aknp= &ak->left;
					
				/* if this does not exist, add a new node, otherwise continue... */
				if (*aknp == NULL) {
					/* add a new node representing this, and attach it to the relevant place */
					new_ak= bezt_to_new_actkeycolumn(bezt);
					new_ak->parent= ak;
					*aknp= new_ak;
					break;
				}
				else
					akn= *aknp;
			}
		}
	}
	
	/* now, balance the tree taking into account this newly added node */
	BLI_dlrbTree_insert(keys, (DLRBT_Node *)new_ak);
}
Esempio n. 3
0
/* Node updater callback used for building ActKeyColumns from BezTriples */
static void nupdate_ak_bezt(void *node, void *data)
{
	ActKeyColumn *ak = (ActKeyColumn *)node;
	BezTriple *bezt = (BezTriple *)data;
	
	/* set selection status and 'touched' status */
	if (BEZSELECTED(bezt)) ak->sel = SELECT;
	ak->modified += 1;
	
	/* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
	if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
		ak->key_type = BEZT_KEYTYPE_KEYFRAME;
}
Esempio n. 4
0
/* Create a ActKeyColumn from a BezTriple */
static ActKeyColumn *bezt_to_new_actkeycolumn(BezTriple *bezt)
{
	ActKeyColumn *ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
	
	/* store settings based on state of BezTriple */
	ak->cfra= bezt->vec[1][0];
	ak->sel= BEZSELECTED(bezt) ? SELECT : 0;
	ak->key_type= BEZKEYTYPE(bezt); 
	
	/* set 'modified', since this is used to identify long keyframes */
	ak->modified = 1;
	
	return ak;
}
Esempio n. 5
0
/* New node callback used for building ActKeyColumns from BezTriples */
static DLRBT_Node *nalloc_ak_bezt(void *data)
{
	ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
	BezTriple *bezt = (BezTriple *)data;
	
	/* store settings based on state of BezTriple */
	ak->cfra = bezt->vec[1][0];
	ak->sel = BEZSELECTED(bezt) ? SELECT : 0;
	ak->key_type = BEZKEYTYPE(bezt);
	
	/* set 'modified', since this is used to identify long keyframes */
	ak->modified = 1;
	
	return (DLRBT_Node *)ak;
}
Esempio n. 6
0
/* Create a ActKeyColumn for a pair of BezTriples */
static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
{
	ActKeyBlock *ab = MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");

	ab->start = prev->vec[1][0];
	ab->end = beztn->vec[1][0];
	ab->val = beztn->vec[1][1];

	ab->sel = (BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn)) ? SELECT : 0;
	ab->modified = 1;

	if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
		ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;

	return ab;
}
Esempio n. 7
0
static short set_keytype_jitter(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
{
	if (bezt->f2 & SELECT) 
		BEZKEYTYPE(bezt) = BEZT_KEYTYPE_JITTER;
	return 0;
}
Esempio n. 8
0
static short set_keytype_extreme(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
{
	if (bezt->f2 & SELECT) 
		BEZKEYTYPE(bezt) = BEZT_KEYTYPE_EXTREME;
	return 0;
}
Esempio n. 9
0
static short set_keytype_breakdown(KeyframeEditData *UNUSED(ked), BezTriple *bezt) 
{
	if (bezt->f2 & SELECT) 
		BEZKEYTYPE(bezt) = BEZT_KEYTYPE_BREAKDOWN;
	return 0;
}
/* Basic F-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only
 * optionally clears up curve if one keyframe with default value remains */
void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
{
	FCurve *fcu = (FCurve *)ale->key_data;
	BezTriple *old_bezts, *bezt, *beztn;
	BezTriple *lastb;
	int totCount, i;
	
	/* check if any points  */
	if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) ||
	    (!cleardefault && fcu->totvert == 1))
	{
		return;
	}

	/* make a copy of the old BezTriples, and clear F-Curve */
	old_bezts = fcu->bezt;
	totCount = fcu->totvert;
	fcu->bezt = NULL;
	fcu->totvert = 0;
	
	/* now insert first keyframe, as it should be ok */
	bezt = old_bezts;
	insert_vert_fcurve(fcu, bezt->vec[1][0], bezt->vec[1][1], BEZKEYTYPE(bezt), 0);
	if (!(bezt->f2 & SELECT)) {
		lastb = fcu->bezt;
		lastb->f1 = lastb->f2 = lastb->f3 = 0;
	}
	
	/* Loop through BezTriples, comparing them. Skip any that do 
	 * not fit the criteria for "ok" points.
	 */
	for (i = 1; i < totCount; i++) {
		float prev[2], cur[2], next[2];

		/* get BezTriples and their values */
		if (i < (totCount - 1)) {
			beztn = (old_bezts + (i + 1));
			next[0] = beztn->vec[1][0]; next[1] = beztn->vec[1][1];
		}
		else {
			beztn = NULL;
			next[0] = next[1] = 0.0f;
		}
		lastb = (fcu->bezt + (fcu->totvert - 1));
		bezt = (old_bezts + i);
		
		/* get references for quicker access */
		prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1];
		cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1];
		
		if (!(bezt->f2 & SELECT)) {
			insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
			lastb = (fcu->bezt + (fcu->totvert - 1));
			lastb->f1 = lastb->f2 = lastb->f3 = 0;
			continue;
		}
		
		/* check if current bezt occurs at same time as last ok */
		if (IS_EQT(cur[0], prev[0], thresh)) {
			/* If there is a next beztriple, and if occurs at the same time, only insert 
			 * if there is a considerable distance between the points, and also if the 
			 * current is further away than the next one is to the previous.
			 */
			if (beztn && (IS_EQT(cur[0], next[0], thresh)) &&
			    (IS_EQT(next[1], prev[1], thresh) == 0))
			{
				/* only add if current is further away from previous */
				if (cur[1] > next[1]) {
					if (IS_EQT(cur[1], prev[1], thresh) == 0) {
						/* add new keyframe */
						insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
					}
				}
			}
			else {
				/* only add if values are a considerable distance apart */
				if (IS_EQT(cur[1], prev[1], thresh) == 0) {
					/* add new keyframe */
					insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
				}
			}
		}
		else {
			/* checks required are dependent on whether this is last keyframe or not */
			if (beztn) {
				/* does current have same value as previous and next? */
				if (IS_EQT(cur[1], prev[1], thresh) == 0) {
					/* add new keyframe*/
					insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
				}
				else if (IS_EQT(cur[1], next[1], thresh) == 0) {
					/* add new keyframe */
					insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
				}
			}
			else {
				/* add if value doesn't equal that of previous */
				if (IS_EQT(cur[1], prev[1], thresh) == 0) {
					/* add new keyframe */
					insert_vert_fcurve(fcu, cur[0], cur[1], BEZKEYTYPE(bezt), 0);
				}
			}
		}
	}
	
	/* now free the memory used by the old BezTriples */
	if (old_bezts)
		MEM_freeN(old_bezts);

	/* final step, if there is just one key in fcurve, check if it's
	 * the default value and if is, remove fcurve completely. */
	if (cleardefault && fcu->totvert == 1) {
		float default_value = 0.0f;
		PointerRNA id_ptr, ptr;
		PropertyRNA *prop;
		RNA_id_pointer_create(ale->id, &id_ptr);

		/* get property to read from, and get value as appropriate */
		if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
			if (RNA_property_type(prop) == PROP_FLOAT)
				default_value = RNA_property_float_get_default_index(&ptr, prop, fcu->array_index);
		}

		if (fcu->bezt->vec[1][1] == default_value) {
			clear_fcurve_keys(fcu);

			/* check if curve is really unused and if it is, return signal for deletion */
			if ((list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
			    (fcu->driver == NULL))
			{
				AnimData *adt = ale->adt;
				ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
				ale->key_data = NULL;
			}
		}
	}
}
Esempio n. 11
0
static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt, BezTriple *beztn)
{
	ActKeyBlock *new_ab = NULL;
	BezTriple *prev = NULL;

	/* get the BezTriple immediately before the given one which has the same value */
	if (beztn != first_bezt) {
		/* XXX: Unless I'm overlooking some details from the past, this should be sufficient?
		 *      The old code did some elaborate stuff trying to find keyframe columns for
		 *      the given BezTriple, then step backwards to the column before that, and find
		 *      an appropriate BezTriple with matching values there. Maybe that was warranted
		 *      in the past, but now, that list is only ever filled with keyframes from the
		 *      current FCurve.
		 *
		 *      -- Aligorith (20140415)
		 */
		prev = beztn - 1;
	}


	/* check if block needed */
	if (prev == NULL) return;

	if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) {
		/* Animator tagged a "moving hold"
		 *   - Previous key must also be tagged as a moving hold, otherwise
		 *     we're just dealing with the first of a pair, and we don't
		 *     want to be creating any phantom holds...
		 */
		if (BEZKEYTYPE(prev) != BEZT_KEYTYPE_MOVEHOLD)
			return;
	}
	else {
		/* Check for same values...
		 *  - Handles must have same central value as each other
		 *  - Handles which control that section of the curve must be constant
		 */
		if (IS_EQF(beztn->vec[1][1], prev->vec[1][1]) == 0) return;

		if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) == 0) return;
		if (IS_EQF(prev->vec[1][1], prev->vec[2][1]) == 0) return;
	}

	/* if there are no blocks already, just add as root */
	if (blocks->root == NULL) {
		/* just add this as the root, then call the tree-balancing functions to validate */
		new_ab = bezts_to_new_actkeyblock(prev, beztn);
		blocks->root = (DLRBT_Node *)new_ab;
	}
	else {
		ActKeyBlock *ab, *abn = NULL;

		/* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
		 * Note: we perform a tree traversal here NOT a standard linked-list traversal...
		 * Note: we can't search from end to try to optimize this as it causes errors there's
		 *      an A ___ B |---| B situation
		 */
		// FIXME: here there is a bug where we are trying to get the summary for the following channels
		//		A|--------------|A ______________ B|--------------|B
		//		A|------------------------------------------------|A
		//		A|----|A|---|A|-----------------------------------|A
		for (ab = blocks->root; ab; ab = abn) {
			/* check if this is a match, or whether we go left or right
			 * NOTE: we now use a float threshold to prevent precision errors causing problems with summaries
			 */
			if (IS_EQT(ab->start, prev->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
				/* set selection status and 'touched' status */
				if (BEZT_ISSEL_ANY(beztn))
					ab->sel = SELECT;

				/* XXX: only when the first one was a moving hold? */
				if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
					ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;

				ab->modified++;

				/* done... no need to insert */
				return;
			}
			else {
				ActKeyBlock **abnp = NULL; /* branch to go down - used to hook new blocks to parents */

				/* check if go left or right, but if not available, add new node */
				if (ab->start < prev->vec[1][0])
					abnp = &ab->right;
				else
					abnp = &ab->left;

				/* if this does not exist, add a new node, otherwise continue... */
				if (*abnp == NULL) {
					/* add a new node representing this, and attach it to the relevant place */
					new_ab = bezts_to_new_actkeyblock(prev, beztn);
					new_ab->parent = ab;
					*abnp = new_ab;
					break;
				}
				else
					abn = *abnp;
			}
		}
	}

	/* now, balance the tree taking into account this newly added node */
	BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
}
Esempio n. 12
0
static short set_keytype_moving_hold(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
	if (bezt->f2 & SELECT)
		BEZKEYTYPE(bezt) = BEZT_KEYTYPE_MOVEHOLD;
	return 0;
}