[Bf-blender-cvs] [daccaa7] master: Patch T22084: Robert Penner Easing Equations for FCurves

Joshua Leung noreply at git.blender.org
Fri Mar 21 15:00:57 CET 2014


Commit: daccaa713b6e66af4b958fa373b31d557a4caa33
Author: Joshua Leung
Date:   Sat Mar 22 02:50:24 2014 +1300
https://developer.blender.org/rBdaccaa713b6e66af4b958fa373b31d557a4caa33

Patch T22084: Robert Penner Easing Equations for FCurves

This commit introduces support for a number of new interpolation types
which are useful for motion-graphics work. These define a number of
"easing equations" (basically, equations which define some preset
ways that one keyframe transitions to another) which reduce the amount
of manual work (inserting and tweaking keyframes) to achieve certain
common effects. For example, snappy movements, and fake-physics such
as bouncing/springing effects.

The additional interpolation types introduced in this commit can be found
in many packages and toolkits (notably Qt and all modern web browsers).
For more info and a few live demos, see [1] and [2].


Credits:
* Dan Eicher (dna)              - Original patch
* Thomas Beck (plasmasolutions) - Porting/updating patch to 2.70 codebase
* Joshua Leung (aligorith)      - Code review and a few polishing tweaks

Additional Resources:
[1] http://easings.net
[2] http://www.robertpenner.com/easing/

===================================================================

M	release/scripts/startup/bl_ui/space_graph.py
M	source/blender/blenkernel/intern/fcurve.c
A	source/blender/blenlib/BLI_math_easing.h
M	source/blender/blenlib/CMakeLists.txt
A	source/blender/blenlib/intern/math_easing.c
M	source/blender/editors/animation/keyframes_edit.c
M	source/blender/editors/include/ED_keyframes_edit.h
M	source/blender/editors/space_graph/graph_buttons.c
M	source/blender/editors/space_graph/graph_draw.c
M	source/blender/editors/space_graph/graph_edit.c
M	source/blender/editors/space_graph/graph_intern.h
M	source/blender/editors/space_graph/graph_ops.c
M	source/blender/makesdna/DNA_curve_types.h
M	source/blender/makesrna/RNA_enum_types.h
M	source/blender/makesrna/intern/rna_curve.c
M	source/blender/makesrna/intern/rna_fcurve.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index e4fb538..67fc286 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -227,6 +227,7 @@ class GRAPH_MT_key(Menu):
         layout.separator()
         layout.operator_menu_enum("graph.handle_type", "type", text="Handle Type")
         layout.operator_menu_enum("graph.interpolation_type", "type", text="Interpolation Mode")
+        layout.operator_menu_enum("graph.easing_type", "type", text="Easing Type")
 
         layout.separator()
         layout.operator("graph.clean")
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index c6b64a1..e496513 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -45,6 +45,7 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
+#include "BLI_math_easing.h"
 #include "BLI_utildefines.h"
 
 #include "BLF_translation.h"
@@ -2080,49 +2081,199 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
 		}
 		/* evaltime occurs within the interval defined by these two keyframes */
 		else if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) {
+			const float begin = prevbezt->vec[1][1];
+			const float change = bezt->vec[1][1] - prevbezt->vec[1][1];
+			const float duration = bezt->vec[1][0] - prevbezt->vec[1][0];
+			const float time = evaltime - prevbezt->vec[1][0];
+			const float amplitude = prevbezt->amplitude;
+			const float period = prevbezt->period;
+			
 			/* value depends on interpolation mode */
-			if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES)) {
+			if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES) || (duration == 0)) {
 				/* constant (evaltime not relevant, so no interpolation needed) */
 				cvalue = prevbezt->vec[1][1];
 			}
-			else if (prevbezt->ipo == BEZT_IPO_LIN) {
-				/* linear - interpolate between values of the two keyframes */
-				fac = bezt->vec[1][0] - prevbezt->vec[1][0];
-				
-				/* prevent division by zero */
-				if (fac) {
-					fac = (evaltime - prevbezt->vec[1][0]) / fac;
-					cvalue = prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1]));
-				}
-				else {
-					cvalue = prevbezt->vec[1][1];
-				}
-			}
 			else {
-				/* bezier interpolation */
-				/* (v1, v2) are the first keyframe and its 2nd handle */
-				v1[0] = prevbezt->vec[1][0];
-				v1[1] = prevbezt->vec[1][1];
-				v2[0] = prevbezt->vec[2][0];
-				v2[1] = prevbezt->vec[2][1];
-				/* (v3, v4) are the last keyframe's 1st handle + the last keyframe */
-				v3[0] = bezt->vec[0][0];
-				v3[1] = bezt->vec[0][1];
-				v4[0] = bezt->vec[1][0];
-				v4[1] = bezt->vec[1][1];
-				
-				/* adjust handles so that they don't overlap (forming a loop) */
-				correct_bezpart(v1, v2, v3, v4);
-				
-				/* try to get a value for this position - if failure, try another set of points */
-				b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl);
-				if (b) {
-					berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
-					cvalue = opl[0];
-					/* break; */
-				}
-				else {
-					if (G.debug & G_DEBUG) printf("    ERROR: findzero() failed at %f with %f %f %f %f\n", evaltime, v1[0], v2[0], v3[0], v4[0]);
+				switch (prevbezt->ipo) {
+					/* interpolation ...................................... */
+					case BEZT_IPO_BEZ:
+						/* bezier interpolation */
+						/* (v1, v2) are the first keyframe and its 2nd handle */
+						v1[0] = prevbezt->vec[1][0];
+						v1[1] = prevbezt->vec[1][1];
+						v2[0] = prevbezt->vec[2][0];
+						v2[1] = prevbezt->vec[2][1];
+						/* (v3, v4) are the last keyframe's 1st handle + the last keyframe */
+						v3[0] = bezt->vec[0][0];
+						v3[1] = bezt->vec[0][1];
+						v4[0] = bezt->vec[1][0];
+						v4[1] = bezt->vec[1][1];
+						
+						/* adjust handles so that they don't overlap (forming a loop) */
+						correct_bezpart(v1, v2, v3, v4);
+						
+						/* try to get a value for this position - if failure, try another set of points */
+						b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl);
+						if (b) {
+							berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
+							cvalue = opl[0];
+							/* break; */
+						}
+						else {
+							if (G.debug & G_DEBUG) printf("    ERROR: findzero() failed at %f with %f %f %f %f\n", evaltime, v1[0], v2[0], v3[0], v4[0]);
+						}
+						break;
+						
+					case BEZT_IPO_LIN:
+						/* linear - simply linearly interpolate between values of the two keyframes */
+						cvalue = LinearEase(time, begin, change, duration);
+						break;
+						
+					/* easing ............................................ */
+					case BEZT_IPO_BACK:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = BackEaseIn(time, begin, change, duration, prevbezt->back);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = BackEaseOut(time, begin, change, duration, prevbezt->back);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = BackEaseInOut(time, begin, change, duration, prevbezt->back);
+								break;
+						}
+						break;
+					
+					case BEZT_IPO_BOUNCE:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = BounceEaseIn(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = BounceEaseOut(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = BounceEaseInOut(time, begin, change, duration);
+								break;
+						}
+						break;
+					
+					case BEZT_IPO_CIRC:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = CircEaseIn(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = CircEaseOut(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = CircEaseInOut(time, begin, change, duration);
+								break;
+						}
+						break;
+
+					case BEZT_IPO_CUBIC:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = CubicEaseIn(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = CubicEaseOut(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = CubicEaseInOut(time, begin, change, duration);
+								break;
+						}
+						break;
+					
+					case BEZT_IPO_ELASTIC:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = ElasticEaseIn(time, begin, change, duration, amplitude, period);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = ElasticEaseOut(time, begin, change, duration, amplitude, period);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = ElasticEaseInOut(time, begin, change, duration, amplitude, period);
+								break;
+						}
+						break;
+					
+					case BEZT_IPO_EXPO:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = ExpoEaseIn(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = ExpoEaseOut(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = ExpoEaseInOut(time, begin, change, duration);
+								break;
+						}
+						break;
+					
+					case BEZT_IPO_QUAD:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = QuadEaseIn(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = QuadEaseOut(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = QuadEaseInOut(time, begin, change, duration);
+								break;
+						}
+						break;
+					
+					case BEZT_IPO_QUART:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = QuartEaseIn(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = QuartEaseOut(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = QuartEaseInOut(time, begin, change, duration);
+								break;
+						}
+						break;
+					
+					case BEZT_IPO_QUINT:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = QuintEaseIn(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = QuintEaseOut(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = QuintEaseInOut(time, begin, change, duration);
+								break;
+						}
+						break;
+					
+					case BEZT_IPO_SINE:
+						switch (prevbezt->easing) {
+							case BEZT_IPO_EASE_IN:
+								cvalue = SineEaseIn(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_OUT:
+								cvalue = SineEaseOut(time, begin, change, duration);
+								break;
+							case BEZT_IPO_EASE_IN_OUT:
+								cvalue = SineEaseInOut(time, begin, change, duration);
+								break;
+						}
+						break;
+					
+					
+					default:
+						cvalue = prevbezt->vec[1][1];
+						break;
 				}
 			}
 		}
diff --git a/source/blender/blenlib/BLI_math_easing.h b/source/blender/blenlib/BLI_math_easing.h
new file mode 100644
index 0000000..c651849
--- /dev/null
+++ b/source/blender/blenlib/BLI_math_easing.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright © 2001 Robert Penner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   * Neither the name of the author nor the names of contributors may be
+ *     used to endorse or promote products derived from this software without
+ *     specific prior w

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list