コード例 #1
0
/* Only delete the nominated keyframe from provided F-Curve. 
 * Not recommended to be used many times successively. For that
 * there is delete_fcurve_keys(). 
 */
void delete_fcurve_key(FCurve *fcu, int index, short do_recalc)
{
	/* sanity check */
	if (fcu == NULL) 
		return;
		
	/* verify the index:
	 *	1) cannot be greater than the number of available keyframes
	 *	2) negative indices are for specifying a value from the end of the array
	 */
	if (abs(index) >= fcu->totvert)
		return;
	else if (index < 0)
		index += fcu->totvert;
	
	/* Delete this keyframe */
	memmove(&fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1));
	fcu->totvert--;

	if (fcu->totvert == 0) {
		if (fcu->bezt)
			MEM_freeN(fcu->bezt);
		fcu->bezt = NULL;
	}
	
	/* recalc handles - only if it won't cause problems */
	if (do_recalc)
		calchandles_fcurve(fcu);
}
コード例 #2
0
ファイル: keyframes_general.c プロジェクト: jinjoh/NOOR
/* 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);
}
コード例 #3
0
static void rna_FCurve_convert_to_keyframes(FCurve *fcu, ReportList *reports, int start, int end)
{
	if (start >= end) {
		BKE_reportf(reports, RPT_ERROR, "Invalid frame range (%d - %d)", start, end);
	}
	else if (fcu->bezt) {
		BKE_report(reports, RPT_WARNING, "FCurve has already keyframes");
	}
	else if (!fcu->fpt) {
		BKE_report(reports, RPT_WARNING, "FCurve has no sample points");
	}
	else {
		BezTriple *bezt;
		FPoint *fpt = fcu->fpt;
		int tot_kf = end - start;
		int tot_sp = fcu->totvert;

		bezt = fcu->bezt = MEM_callocN(sizeof(*fcu->bezt) * (size_t)tot_kf, __func__);
		fcu->totvert = tot_kf;

		/* Get first sample point to 'copy' as keyframe. */
		for (; tot_sp && (fpt->vec[0] < (float)start); fpt++, tot_sp--);

		/* Add heading dummy flat points if needed. */
		for (; tot_kf && (fpt->vec[0] > (float)start); start++, bezt++, tot_kf--) {
			/* Linear interpolation, of course. */
			bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
			bezt->ipo = BEZT_IPO_LIN;
			bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
			bezt->vec[1][0] = (float)start;
			bezt->vec[1][1] = fpt->vec[1];
		}

		/* Copy actual sample points. */
		for (; tot_kf && tot_sp; start++, bezt++, tot_kf--, fpt++, tot_sp--) {
			/* Linear interpolation, of course. */
			bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
			bezt->ipo = BEZT_IPO_LIN;
			bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
			copy_v2_v2(bezt->vec[1], fpt->vec);
		}

		/* Add leading dummy flat points if needed. */
		for (fpt--; tot_kf; start++, bezt++, tot_kf--) {
			/* Linear interpolation, of course. */
			bezt->f1 = bezt->f2 = bezt->f3 = SELECT;
			bezt->ipo = BEZT_IPO_LIN;
			bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
			bezt->vec[1][0] = (float)start;
			bezt->vec[1][1] = fpt->vec[1];
		}

		MEM_SAFE_FREE(fcu->fpt);

		/* Not strictly needed since we use linear interpolation, but better be consistent here. */
		calchandles_fcurve(fcu);
		WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
	}
}
コード例 #4
0
/* update callback for active keyframe properties - base updates stuff */
static void graphedit_activekey_update_cb(bContext *UNUSED(C), void *fcu_ptr, void *UNUSED(bezt_ptr))
{
	FCurve *fcu = (FCurve *)fcu_ptr;
	
	/* make sure F-Curve and its handles are still valid after this editing */
	sort_time_fcurve(fcu);
	calchandles_fcurve(fcu);
}
コード例 #5
0
ファイル: fmodifier.c プロジェクト: wangyxuan/blender
/* Add a new F-Curve Modifier to the given F-Curve of a certain type */
FModifier *add_fmodifier(ListBase *modifiers, int type, FCurve *owner_fcu)
{
  const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(type);
  FModifier *fcm;

  /* sanity checks */
  if (ELEM(NULL, modifiers, fmi)) {
    return NULL;
  }

  /* special checks for whether modifier can be added */
  if ((modifiers->first) && (type == FMODIFIER_TYPE_CYCLES)) {
    /* cycles modifier must be first in stack, so for now, don't add if it can't be */
    /* TODO: perhaps there is some better way, but for now, */
    CLOG_STR_ERROR(&LOG,
                   "Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be "
                   "first in stack.");
    return NULL;
  }

  /* add modifier itself */
  fcm = MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
  fcm->type = type;
  fcm->flag = FMODIFIER_FLAG_EXPANDED;
  fcm->curve = owner_fcu;
  fcm->influence = 1.0f;
  BLI_addtail(modifiers, fcm);

  /* tag modifier as "active" if no other modifiers exist in the stack yet */
  if (BLI_listbase_is_single(modifiers)) {
    fcm->flag |= FMODIFIER_FLAG_ACTIVE;
  }

  /* add modifier's data */
  fcm->data = MEM_callocN(fmi->size, fmi->structName);

  /* init custom settings if necessary */
  if (fmi->new_data) {
    fmi->new_data(fcm->data);
  }

  /* update the fcurve if the Cycles modifier is added */
  if ((owner_fcu) && (type == FMODIFIER_TYPE_CYCLES)) {
    calchandles_fcurve(owner_fcu);
  }

  /* return modifier for further editing */
  return fcm;
}
コード例 #6
0
void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
{
	KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes();
	int numScenes = scenes->size();
	int i;
	for (i = 0; i < numScenes; i++) {
		KX_Scene *scene = scenes->at(i);
		//PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
		CListValue *parentList = scene->GetRootParentList();
		int numObjects = parentList->GetCount();
		int g;
		for (g = 0; g < numObjects; g++) {
			KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g);
			if (gameObj->IsRecordAnimation()) {
				Object *blenderObject = gameObj->GetBlenderObject();
				if (blenderObject && blenderObject->adt) {
					bAction *act = verify_adt_action(&blenderObject->id, false);
					FCurve *fcu;

					if (!act) {
						continue;
					}

					/* for now, not much choice but to run this on all curves... */
					for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
						/* Note: calling `sort_time_fcurve()` here is not needed, since
						 *       all keys have been added in 'right' order. */
						calchandles_fcurve(fcu);
					}
#if 0
					// XXX animato
					Ipo* ipo = blenderObject->ipo;

					//create the curves, if not existing
					//testhandles_ipocurve checks for NULL
					testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"));
					testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"));
					testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"));
					testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"));
					testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"));
					testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"));
#endif
				}
			}
		}
	}
}
コード例 #7
0
ファイル: keyframes_general.c プロジェクト: jinjoh/NOOR
/* Only delete the nominated keyframe from provided ipo-curve. 
 * Not recommended to be used many times successively. For that
 * there is delete_ipo_keys(). 
 */
void delete_fcurve_key(FCurve *fcu, int index, short do_recalc)
{
	/* firstly check that index is valid */
	if (index < 0) 
		index *= -1;
	if (fcu == NULL) 
		return;
	if (index >= fcu->totvert)
		return;
	
	/*	Delete this key */
	memmove(&fcu->bezt[index], &fcu->bezt[index+1], sizeof(BezTriple)*(fcu->totvert-index-1));
	fcu->totvert--;
	
	/* recalc handles - only if it won't cause problems */
	if (do_recalc)
		calchandles_fcurve(fcu);
}
コード例 #8
0
ファイル: fmodifier.c プロジェクト: wangyxuan/blender
/* Remove and free the given F-Modifier from the given stack  */
bool remove_fmodifier(ListBase *modifiers, FModifier *fcm)
{
  const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(fcm);

  /* sanity check */
  if (fcm == NULL) {
    return false;
  }

  /* removing the cycles modifier requires a handle update */
  FCurve *update_fcu = (fcm->type == FMODIFIER_TYPE_CYCLES) ? fcm->curve : NULL;

  /* free modifier's special data (stored inside fcm->data) */
  if (fcm->data) {
    if (fmi && fmi->free_data) {
      fmi->free_data(fcm);
    }

    /* free modifier's data (fcm->data) */
    MEM_freeN(fcm->data);
  }

  /* remove modifier from stack */
  if (modifiers) {
    BLI_freelinkN(modifiers, fcm);

    /* update the fcurve if the Cycles modifier is removed */
    if (update_fcu) {
      calchandles_fcurve(update_fcu);
    }

    return true;
  }
  else {
    /* XXX this case can probably be removed some day, as it shouldn't happen... */
    CLOG_STR_ERROR(&LOG, "no modifier stack given");
    MEM_freeN(fcm);
    return false;
  }
}
コード例 #9
0
// used to be recalc_*_ipos() where * was object or action
void ANIM_editkeyframes_refresh(bAnimContext *ac)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	/* filter animation data */
	filter = ANIMFILTER_DATA_VISIBLE;
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* loop over F-Curves that are likely to have been edited, and check them */
	for (ale = anim_data.first; ale; ale = ale->next) {
		FCurve *fcu = ale->key_data;
		
		/* make sure keyframes in F-Curve are all in order, and handles are in valid positions */
		sort_time_fcurve(fcu);
		calchandles_fcurve(fcu);
	}
	
	/* free temp data */
	ANIM_animdata_freelist(&anim_data);
}
コード例 #10
0
ファイル: anim_deps.c プロジェクト: greg100795/blender-git
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
{
	bAnimListElem *ale;

	if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
#ifdef DEBUG
		/* quiet assert */
		for (ale = anim_data->first; ale; ale = ale->next) {
			ale->update = 0;
		}
#endif
		return;
	}

	for (ale = anim_data->first; ale; ale = ale->next) {
		FCurve *fcu = ale->key_data;

		if (ale->update & ANIM_UPDATE_ORDER) {
			ale->update &= ~ANIM_UPDATE_ORDER;
			if (fcu)
				sort_time_fcurve(fcu);
		}

		if (ale->update & ANIM_UPDATE_HANDLES) {
			ale->update &= ~ANIM_UPDATE_HANDLES;
			if (fcu)
				calchandles_fcurve(fcu);
		}

		if (ale->update & ANIM_UPDATE_DEPS) {
			ale->update &= ~ANIM_UPDATE_DEPS;
			ANIM_list_elem_update(ac->scene, ale);
		}

		BLI_assert(ale->update == 0);
	}
}
コード例 #11
0
/* helper for paste_animedit_keys() - performs the actual pasting */
static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode)
{
	BezTriple *bezt;
	int i;

	/* First de-select existing FCurve's keyframes */
	for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
		bezt->f2 &= ~SELECT;
	}

	/* mix mode with existing data */
	switch (merge_mode) {
		case KEYFRAME_PASTE_MERGE_MIX:
			/* do-nothing */
			break;
			
		case KEYFRAME_PASTE_MERGE_OVER:
			/* remove all keys */
			clear_fcurve_keys(fcu);
			break;
			
		case KEYFRAME_PASTE_MERGE_OVER_RANGE:
		case KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL:
		{
			float f_min;
			float f_max;
			
			if (merge_mode == KEYFRAME_PASTE_MERGE_OVER_RANGE) {
				f_min = aci->bezt[0].vec[1][0] + offset;
				f_max = aci->bezt[aci->totvert - 1].vec[1][0] + offset;
			}
			else { /* Entire Range */
				f_min = animcopy_firstframe + offset;
				f_max = animcopy_lastframe + offset;
			}
			
			/* remove keys in range */
			if (f_min < f_max) {
				/* select verts in range for removal */
				for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
					if ((f_min < bezt[0].vec[1][0]) && (bezt[0].vec[1][0] < f_max)) {
						bezt->f2 |= SELECT;
					}
				}
				
				/* remove frames in the range */
				delete_fcurve_keys(fcu);
			}
			break;
		}
	}
	
	/* just start pasting, with the the first keyframe on the current frame, and so on */
	for (i = 0, bezt = aci->bezt; i < aci->totvert; i++, bezt++) {
		/* temporarily apply offset to src beztriple while copying */
		bezt->vec[0][0] += offset;
		bezt->vec[1][0] += offset;
		bezt->vec[2][0] += offset;
		
		/* insert the keyframe
		 * NOTE: no special flags here for now
		 */
		insert_bezt_fcurve(fcu, bezt, 0); 
		
		/* un-apply offset from src beztriple after copying */
		bezt->vec[0][0] -= offset;
		bezt->vec[1][0] -= offset;
		bezt->vec[2][0] -= offset;
	}
	
	/* recalculate F-Curve's handles? */
	calchandles_fcurve(fcu);
}
コード例 #12
0
// TODO: introduce scaling factor for weighting falloff
void smooth_fcurve(FCurve *fcu)
{
	BezTriple *bezt;
	int i, x, totSel = 0;

	if (fcu->bezt == NULL) {
		return;
	}

	/* first loop through - count how many verts are selected */
	bezt = fcu->bezt;
	for (i = 0; i < fcu->totvert; i++, bezt++) {
		if (BEZSELECTED(bezt))
			totSel++;
	}
	
	/* if any points were selected, allocate tSmooth_Bezt points to work on */
	if (totSel >= 3) {
		tSmooth_Bezt *tarray, *tsb;
		
		/* allocate memory in one go */
		tsb = tarray = MEM_callocN(totSel * sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
		
		/* populate tarray with data of selected points */
		bezt = fcu->bezt;
		for (i = 0, x = 0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
			if (BEZSELECTED(bezt)) {
				/* tsb simply needs pointer to vec, and index */
				tsb->h1 = &bezt->vec[0][1];
				tsb->h2 = &bezt->vec[1][1];
				tsb->h3 = &bezt->vec[2][1];
				
				/* advance to the next tsb to populate */
				if (x < totSel - 1)
					tsb++;
				else
					break;
			}
		}
			
		/* calculate the new smoothed F-Curve's with weighted averages:
		 *	- this is done with two passes to avoid progressive corruption errors
		 *	- uses 5 points for each operation (which stores in the relevant handles)
		 *	-   previous: w/a ratio = 3:5:2:1:1
		 *	-   next: w/a ratio = 1:1:2:5:3
		 */
		
		/* round 1: calculate smoothing deltas and new values */ 
		tsb = tarray;
		for (i = 0; i < totSel; i++, tsb++) {
			/* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */
			if (ELEM(i, 0, (totSel - 1)) == 0) {
				const tSmooth_Bezt *tP1 = tsb - 1;
				const tSmooth_Bezt *tP2 = (i - 2 > 0) ? (tsb - 2) : (NULL);
				const tSmooth_Bezt *tN1 = tsb + 1;
				const tSmooth_Bezt *tN2 = (i + 2 < totSel) ? (tsb + 2) : (NULL);
				
				const float p1 = *tP1->h2;
				const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
				const float c1 = *tsb->h2;
				const float n1 = *tN1->h2;
				const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
				
				/* calculate previous and next, then new position by averaging these */
				tsb->y1 = (3 * p2 + 5 * p1 + 2 * c1 + n1 + n2) / 12;
				tsb->y3 = (p2 + p1 + 2 * c1 + 5 * n1 + 3 * n2) / 12;
				
				tsb->y2 = (tsb->y1 + tsb->y3) / 2;
			}
		}
		
		/* round 2: apply new values */
		tsb = tarray;
		for (i = 0; i < totSel; i++, tsb++) {
			/* don't touch end points, as their values were't touched above */
			if (ELEM(i, 0, (totSel - 1)) == 0) {
				/* y2 takes the average of the 2 points */
				*tsb->h2 = tsb->y2;
				
				/* handles are weighted between their original values and the averaged values */
				*tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f); 
				*tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f);
			}
		}
		
		/* free memory required for tarray */
		MEM_freeN(tarray);
	}
	
	/* recalculate handles */
	calchandles_fcurve(fcu);
}
コード例 #13
0
static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd)
{
	Scene *scene = CTX_data_scene(C);
	bAction *act;
	FCurve *fcu;
	PointerRNA ptr;
	PropertyRNA *prop = NULL;
	int nbr_gaps = 0, i;
	
	if (gtd->mode == GP_STROKECONVERT_TIMING_NONE)
		return;
	
	/* gap_duration and gap_randomness are in frames, but we need seconds!!! */
	gtd->gap_duration = FRA2TIME(gtd->gap_duration);
	gtd->gap_randomness = FRA2TIME(gtd->gap_randomness);
	
	/* Enable path! */
	cu->flag |= CU_PATH;
	cu->pathlen = gtd->frame_range;
	
	/* Get RNA pointer to read/write path time values */
	RNA_id_pointer_create((ID *)cu, &ptr);
	prop = RNA_struct_find_property(&ptr, "eval_time");
	
	/* Ensure we have an F-Curve to add keyframes to */
	act = verify_adt_action((ID *)cu, true);
	fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, true);
	
	if (G.debug & G_DEBUG) {
		printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
		for (i = 0; i < gtd->num_points; i++) {
			printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
		}
	}
	
	if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) {
		float cfra;
		
		/* Linear extrapolation! */
		fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
		
		cu->ctime = 0.0f;
		cfra = (float)gtd->start_frame;
		insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
		
		cu->ctime = cu->pathlen;
		if (gtd->realtime) {
			cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
		}
		else {
			cfra = (float)gtd->end_frame;
		}
		insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
	}
	else {
		/* Use actual recorded timing! */
		RNG *rng = BLI_rng_new(0);
		float time_range;
		
		/* CustomGaps specific */
		float tot_gaps_time = 0.0f;
		
		/* Pre-process gaps, in case we don't want to keep their original timing */
		if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) {
			gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time);
		}
		
		if (gtd->realtime) {
			time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */
		}
		else {
			time_range = (float)(gtd->end_frame - gtd->start_frame);
		}
		
		if (G.debug & G_DEBUG) {
			printf("GP Stroke Path Conversion: Starting keying!\n");
		}
		
		gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range,
		                                       nbr_gaps, tot_gaps_time);
		
		BLI_rng_free(rng);
	}
	
	/* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */
	calchandles_fcurve(fcu);
	
	if (G.debug & G_DEBUG) {
		printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time);
		for (i = 0; i < gtd->num_points; i++) {
			printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]);
		}
		printf("\n\n");
	}
	
	WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
	
	/* send updates */
	DAG_id_tag_update(&cu->id, 0);
}
コード例 #14
0
ファイル: drivers.c プロジェクト: Walid-Shouman/Blender
/* Get (or add relevant data to be able to do so) F-Curve from the driver stack, 
 * for the given Animation Data block. This assumes that all the destinations are valid.
 *	
 *	- add:	0 - don't add anything if not found, 
 *			1 - add new Driver FCurve (with keyframes for visual tweaking),
 *			2 - add new Driver FCurve (with generator, for script backwards compatibility)
 *			-1 - add new Driver FCurve without driver stuff (for pasting)
 */
FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add)
{
	AnimData *adt;
	FCurve *fcu;
	
	/* sanity checks */
	if (ELEM(NULL, id, rna_path))
		return NULL;
	
	/* init animdata if none available yet */
	adt = BKE_animdata_from_id(id);
	if ((adt == NULL) && (add))
		adt = BKE_id_add_animdata(id);
	if (adt == NULL) {
		/* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
		return NULL;
	}
		
	/* try to find f-curve matching for this setting 
	 *	- add if not found and allowed to add one
	 *		TODO: add auto-grouping support? how this works will need to be resolved
	 */
	fcu = list_find_fcurve(&adt->drivers, rna_path, array_index);
	
	if ((fcu == NULL) && (add)) {
		/* use default settings to make a F-Curve */
		fcu = MEM_callocN(sizeof(FCurve), "FCurve");
		
		fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
		
		/* store path - make copy, and store that */
		fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
		fcu->array_index = array_index;
		
		/* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
		if (add > 0) {
			BezTriple *bezt;
			size_t i;
			
			/* add some new driver data */
			fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
			fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG;
			
			/* F-Modifier or Keyframes? */
			// FIXME: replace these magic numbers with defines
			if (add == 2) {
				/* Python API Backwards compatibility hack:
				 * Create FModifier so that old scripts won't break
				 * for now before 2.7 series -- (September 4, 2013)
				 */
				add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
			}
			else {
				/* add 2 keyframes so that user has something to work with 
				 * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
				 *   which can be easily tweaked from there.
				 */
				insert_vert_fcurve(fcu, 0.0f, 0.0f, INSERTKEY_FAST);
				insert_vert_fcurve(fcu, 1.0f, 1.0f, INSERTKEY_FAST);
				
				/* configure this curve to extrapolate */
				for (i = 0, bezt = fcu->bezt;  (i < fcu->totvert) && bezt;  i++, bezt++) {
					bezt->h1 = bezt->h2 = HD_VECT;
				}
				
				fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
				calchandles_fcurve(fcu);
			}
		}
		
		/* just add F-Curve to end of driver list */
		BLI_addtail(&adt->drivers, fcu);
	}
	
	/* return the F-Curve */
	return fcu;
}
コード例 #15
0
/* Use a weighted moving-means method to reduce intensity of fluctuations */
void smooth_fcurve (FCurve *fcu)
{
	BezTriple *bezt;
	int i, x, totSel = 0;
	
	/* first loop through - count how many verts are selected, and fix up handles 
	 *	this is done for both modes
	 */
	bezt= fcu->bezt;
	for (i=0; i < fcu->totvert; i++, bezt++) {						
		if (BEZSELECTED(bezt)) {							
			/* line point's handles up with point's vertical position */
			bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
			if ((bezt->h1==HD_AUTO) || (bezt->h1==HD_VECT)) bezt->h1= HD_ALIGN;
			if ((bezt->h2==HD_AUTO) || (bezt->h2==HD_VECT)) bezt->h2= HD_ALIGN;
			
			/* add value to total */
			totSel++;
		}
	}
	
	/* if any points were selected, allocate tSmooth_Bezt points to work on */
	if (totSel >= 3) {
		tSmooth_Bezt *tarray, *tsb;
		
		/* allocate memory in one go */
		tsb= tarray= MEM_callocN(totSel*sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
		
		/* populate tarray with data of selected points */
		bezt= fcu->bezt;
		for (i=0, x=0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
			if (BEZSELECTED(bezt)) {
				/* tsb simply needs pointer to vec, and index */
				tsb->h1 = &bezt->vec[0][1];
				tsb->h2 = &bezt->vec[1][1];
				tsb->h3 = &bezt->vec[2][1];
				
				/* advance to the next tsb to populate */
				if (x < totSel- 1) 
					tsb++;
				else
					break;
			}
		}
			
		/* calculate the new smoothed F-Curve's with weighted averages:
		 *	- this is done with two passes
		 *	- uses 5 points for each operation (which stores in the relevant handles)
		 *	-	previous: w/a ratio = 3:5:2:1:1
		 *	- 	next: w/a ratio = 1:1:2:5:3
		 */
		
		/* round 1: calculate previous and next */ 
		tsb= tarray;
		for (i=0; i < totSel; i++, tsb++) {
			/* don't touch end points (otherwise, curves slowly explode) */
			if (ELEM(i, 0, (totSel-1)) == 0) {
				const tSmooth_Bezt *tP1 = tsb - 1;
				const tSmooth_Bezt *tP2 = (i-2 > 0) ? (tsb - 2) : (NULL);
				const tSmooth_Bezt *tN1 = tsb + 1;
				const tSmooth_Bezt *tN2 = (i+2 < totSel) ? (tsb + 2) : (NULL);
				
				const float p1 = *tP1->h2;
				const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2);
				const float c1 = *tsb->h2;
				const float n1 = *tN1->h2;
				const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
				
				/* calculate previous and next */
				*tsb->h1= (3*p2 + 5*p1 + 2*c1 + n1 + n2) / 12;
				*tsb->h3= (p2 + p1 + 2*c1 + 5*n1 + 3*n2) / 12;
			}
		}
		
		/* round 2: calculate new values and reset handles */
		tsb= tarray;
		for (i=0; i < totSel; i++, tsb++) {
			/* calculate new position by averaging handles */
			*tsb->h2 = (*tsb->h1 + *tsb->h3) / 2;
			
			/* reset handles now */
			*tsb->h1 = *tsb->h2;
			*tsb->h3 = *tsb->h2;
		}
		
		/* free memory required for tarray */
		MEM_freeN(tarray);
	}
	
	/* recalculate handles */
	calchandles_fcurve(fcu);
}
コード例 #16
0
ファイル: keyframes_general.c プロジェクト: jinjoh/NOOR
/* This function pastes data from the keyframes copy/paste buffer */
short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data)
{
	bAnimListElem *ale;
	const Scene *scene= (ac->scene);
	const float offset = (float)(CFRA - animcopy_firstframe);
	short no_name= 0;
	
	/* check if buffer is empty */
	if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) {
		//error("No data in buffer to paste");
		return -1;
	}
	/* check if single channel in buffer (disregard names if so)  */
	if (animcopybuf.first == animcopybuf.last)
		no_name= 1;
	
	/* from selected channels */
	for (ale= anim_data->first; ale; ale= ale->next) {
		FCurve *fcu = (FCurve *)ale->data;		/* destination F-Curve */
		tAnimCopybufItem *aci= NULL;
		BezTriple *bezt;
		int i;
		
		/* 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)
		 */
		// TODO: the matching algorithm here is pathetic!
		for (aci= animcopybuf.first; aci; aci= aci->next) {
			/* check that paths exist */
			if (aci->rna_path && fcu->rna_path) {
				// FIXME: this breaks for bone names!
				if (strcmp(aci->rna_path, fcu->rna_path) == 0) {
					/* should be a match unless there's more than one of these */
					if ((no_name) || (aci->array_index == fcu->array_index)) 
						break;
				}
			}
		}
		
		
		/* copy the relevant data from the matching buffer curve */
		if (aci) {
			/* just start pasting, with the the first keyframe on the current frame, and so on */
			for (i=0, bezt=aci->bezt; i < aci->totvert; i++, bezt++) {						
				/* temporarily apply offset to src beztriple while copying */
				bezt->vec[0][0] += offset;
				bezt->vec[1][0] += offset;
				bezt->vec[2][0] += offset;
				
				/* insert the keyframe
				 * NOTE: no special flags here for now
				 */
				insert_bezt_fcurve(fcu, bezt, 0); 
				
				/* un-apply offset from src beztriple after copying */
				bezt->vec[0][0] -= offset;
				bezt->vec[1][0] -= offset;
				bezt->vec[2][0] -= offset;
			}
			
			/* recalculate F-Curve's handles? */
			calchandles_fcurve(fcu);
		}
	}
	
	return 0;
}