Пример #1
0
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
{
	ID *id;
	bAction *action;
	FCurve *fcu;
	bool driven;
	bool special;

	fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special);
	
	if (fcu == NULL)
		return;
	
	if (special) {
		/* NLA Strip property */
		if (IS_AUTOKEY_ON(scene)) {
			ReportList *reports = CTX_wm_reports(C);
			ToolSettings *ts = scene->toolsettings;
			
			insert_keyframe_direct(reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, 0);
			WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
		}
	}
	else if (driven) {
		/* Driver - Try to insert keyframe using the driver's input as the frame,
		 * making it easier to set up corrective drivers
		 */
		if (IS_AUTOKEY_ON(scene)) {
			ReportList *reports = CTX_wm_reports(C);
			ToolSettings *ts = scene->toolsettings;
			
			insert_keyframe_direct(reports, but->rnapoin, but->rnaprop, fcu, cfra, ts->keyframe_type, INSERTKEY_DRIVER);
			WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
		}
	}
	else {
		id = but->rnapoin.id.data;
		
		/* TODO: this should probably respect the keyingset only option for anim */
		if (autokeyframe_cfra_can_key(scene, id)) {
			ReportList *reports = CTX_wm_reports(C);
			ToolSettings *ts = scene->toolsettings;
			short flag = ANIM_get_keyframing_flags(scene, 1);
			
			fcu->flag &= ~FCURVE_SELECTED;
			
			/* Note: We use but->rnaindex instead of fcu->array_index,
			 *       because a button may control all items of an array at once.
			 *       E.g., color wheels (see T42567). */
			BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1));
			insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
			                fcu->rna_path, but->rnaindex, cfra, ts->keyframe_type, flag);
			
			WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
		}
	}
}
Пример #2
0
void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
{
	ID *id;
	bAction *action;
	FCurve *fcu;
	bool driven;
	bool special;

	fcu = ui_but_get_fcurve(but, NULL, &action, &driven, &special);
	
	if (fcu == NULL)
		return;
	
	if (special) {
		/* NLA Strip property */
		if (IS_AUTOKEY_ON(scene)) {
			ReportList *reports = CTX_wm_reports(C);
			PointerRNA ptr = {{NULL}};
			PropertyRNA *prop = NULL;
			int index;
			
			UI_context_active_but_prop_get(C, &ptr, &prop, &index);
			
			insert_keyframe_direct(reports, ptr, prop, fcu, cfra, 0);
			WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
		}
	}
	else if (!driven) {
		id = but->rnapoin.id.data;

		/* TODO: this should probably respect the keyingset only option for anim */
		if (autokeyframe_cfra_can_key(scene, id)) {
			ReportList *reports = CTX_wm_reports(C);
			short flag = ANIM_get_keyframing_flags(scene, 1);

			fcu->flag &= ~FCURVE_SELECTED;

			/* Note: We use but->rnaindex instead of fcu->array_index,
			 *       because a button may control all items of an array at once.
			 *       E.g., color wheels (see T42567). */
			BLI_assert((fcu->array_index == but->rnaindex) || (but->rnaindex == -1));
			insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
			                fcu->rna_path, but->rnaindex, cfra, flag);

			WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
		}
	}
}
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);
}
static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu,
                                                   Curve *cu, tGpTimingData *gtd, RNG *rng, const float time_range,
                                                   const int nbr_gaps, const float tot_gaps_time)
{
	/* Use actual recorded timing! */
	const float time_start = (float)gtd->start_frame;
	
	float last_valid_time = 0.0f;
	int end_stroke_idx = -1, start_stroke_idx = 0;
	float end_stroke_time = 0.0f;
	
	/* CustomGaps specific */
	float delta_time = 0.0f, next_delta_time = 0.0f;
	int nbr_done_gaps = 0;
	
	int i;
	float cfra;
	
	/* This is a bit tricky, as:
	 * - We can't add arbitrarily close points on FCurve (in time).
	 * - We *must* have all "caps" points of all strokes in FCurve, as much as possible!
	 */
	for (i = 0; i < gtd->num_points; i++) {
		/* If new stroke... */
		if (i > end_stroke_idx) {
			start_stroke_idx = i;
			delta_time = next_delta_time;
			/* find end of that new stroke */
			end_stroke_idx = gp_find_end_of_stroke_idx(gtd, rng, i, nbr_gaps, &nbr_done_gaps,
			                                           tot_gaps_time, delta_time, &next_delta_time);
			/* This one should *never* be negative! */
			end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range);
		}
		
		/* Simple proportional stuff... */
		cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen;
		cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range);
		
		/* And now, the checks about timing... */
		if (i == start_stroke_idx) {
			/* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and
			 * that the end point of the stroke is far enough!
			 * In case it is not, we keep the end point...
			 * Note that with CustomGaps mode, this is here we set the actual gap timing!
			 */
			if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) {
				if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
					cfra = last_valid_time + MIN_TIME_DELTA;
				}
				insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
				last_valid_time = cfra;
			}
			else if (G.debug & G_DEBUG) {
				printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx);
			}
		}
		else if (i == end_stroke_idx) {
			/* Always try to insert end point of a curve (should be safe enough, anyway...) */
			if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
				cfra = last_valid_time + MIN_TIME_DELTA;
			}
			insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
			last_valid_time = cfra;
		}
		else {
			/* Else ("middle" point), we only insert it if it's far enough from last keyframe,
			 * and also far enough from (not yet added!) end_stroke keyframe!
			 */
			if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) {
				insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_BREAKDOWN, INSERTKEY_FAST);
				last_valid_time = cfra;
			}
			else if (G.debug & G_DEBUG) {
				printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n",
				       i, end_stroke_idx);
			}
		}
	}
}