[libadwaita/wip/exalm/spring-animation-swipes: 27/36] Add velocity parameter




commit dfbfbf00e5e17053e7b0359d443542d4a52f1a56
Author: Manuel Genovés <manuel genoves gmail com>
Date:   Sun Dec 5 20:51:45 2021 +0100

    Add velocity parameter

 src/adw-spring-animation.c | 59 ++++++++++++++++++++++++++++++++++++++--------
 src/adw-spring-animation.h |  3 +++
 2 files changed, 52 insertions(+), 10 deletions(-)
---
diff --git a/src/adw-spring-animation.c b/src/adw-spring-animation.c
index dbee8773..48dad1b3 100644
--- a/src/adw-spring-animation.c
+++ b/src/adw-spring-animation.c
@@ -24,6 +24,7 @@ struct _AdwSpringAnimation
   AdwSpringParams *spring_params;
 
   double initial_velocity;
+  double velocity;
   double epsilon;
   gboolean clamp;
 
@@ -46,6 +47,7 @@ enum {
   PROP_EPSILON,
   PROP_CLAMP,
   PROP_ESTIMATED_DURATION,
+  PROP_VELOCITY,
   LAST_PROP,
 };
 
@@ -61,7 +63,8 @@ static GParamSpec *props[LAST_PROP];
  */
 static double
 oscillate (AdwAnimation *animation,
-           guint         time)
+           guint         time,
+           double       *velocity)
 {
   AdwSpringAnimation *self = ADW_SPRING_ANIMATION (animation);
 
@@ -88,6 +91,10 @@ oscillate (AdwAnimation *animation,
   if (beta < omega0) {
     double omega1 = sqrt ((omega0 * omega0) - (beta * beta));
 
+    if (velocity) {
+      *velocity = envelope * (v0 * cos (omega1 * t) - (x0 * omega1 + (beta * beta * x0 + beta * v0) / 
(omega1)) * sin (omega1 * t));
+      g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VELOCITY]);
+    }
     return self->value_to + envelope * (x0 * cos (omega1 * t) + ((beta * x0 + v0) / omega1) * sin (omega1 * 
t));
   }
 
@@ -95,10 +102,18 @@ oscillate (AdwAnimation *animation,
   if (beta > omega0) {
     double omega2 = sqrt ((beta * beta) - (omega0 * omega0));
 
+    if (velocity) {
+      *velocity = envelope * (v0 * coshl (omega2 * t) + (omega2 * x0 - (beta * beta * x0 + beta * v0) / 
omega2) * sinhl (omega2 * t));
+      g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VELOCITY]);
+    }
     return self->value_to + envelope * (x0 * coshl (omega2 * t) + ((beta * x0 + v0) / omega2) * sinhl 
(omega2 * t));
   }
 
   /* Critically damped */
+  if (velocity) {
+    *velocity = envelope * (beta * x0 + v0) * (1 - beta);
+    g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VELOCITY]);
+  }
   return self->value_to + envelope * (x0 + (beta * x0 + v0) * t);
 }
 
@@ -107,12 +122,12 @@ get_first_zero (AdwAnimation *animation)
 {
   AdwSpringAnimation *self = ADW_SPRING_ANIMATION (animation);
   guint i = 0;
-  double y = oscillate (animation, 0);
+  double y = oscillate (animation, 0, NULL);
 
   while (self->value_to > y) {
     if (i>20000)
       return 0;
-    y = oscillate (animation, i);
+    y = oscillate (animation, i, NULL);
     i++;
   }
 
@@ -160,11 +175,11 @@ estimate_duration (AdwAnimation *animation)
    * Newton's root finding method is a good candidate in this particular case:
    * https://en.wikipedia.org/wiki/Newton%27s_method
    */
-  y0 = oscillate (animation, x0*1000);
-  m = (oscillate (animation, (x0 + DELTA) * 1000) - y0) / DELTA;
+  y0 = oscillate (animation, x0*1000, NULL);
+  m = (oscillate (animation, (x0 + DELTA) * 1000, NULL) - y0) / DELTA;
 
   x1 = (self->value_to - y0 + m * x0) / m;
-  y1 = oscillate (animation, x1*1000);
+  y1 = oscillate (animation, x1*1000, NULL);
 
   while (ABS (self->value_to - y1) > self->epsilon) {
     if (i>1000)
@@ -172,10 +187,10 @@ estimate_duration (AdwAnimation *animation)
     x0 = x1;
     y0 = y1;
 
-    m = (oscillate (animation, (x0 + DELTA) * 1000) - y0) / DELTA;
+    m = (oscillate (animation, (x0 + DELTA) * 1000, NULL) - y0) / DELTA;
 
     x1 = (self->value_to - y0 + m * x0) / m;
-    y1 = oscillate (animation, x1*1000);
+    y1 = oscillate (animation, x1*1000, NULL);
     i++;
   }
 
@@ -205,10 +220,13 @@ adw_spring_animation_calculate_value (AdwAnimation *animation,
 {
   AdwSpringAnimation *self = ADW_SPRING_ANIMATION (animation);
 
-  if (t >= self->estimated_duration)
+  if (t >= self->estimated_duration) {
+    self->velocity = 0;
+    g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VELOCITY]);
     return self->value_to;
+  }
 
-  return oscillate (animation, t);
+  return oscillate (animation, t, &self->velocity);
 }
 
 static void
@@ -268,6 +286,10 @@ adw_spring_animation_get_property (GObject    *object,
     g_value_set_uint (value, adw_spring_animation_get_estimated_duration (self));
     break;
 
+  case PROP_VELOCITY:
+    g_value_set_double (value, adw_spring_animation_get_velocity (self));
+    break;
+
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -384,6 +406,15 @@ adw_spring_animation_class_init (AdwSpringAnimationClass *klass)
                        0,
                        G_PARAM_READABLE);
 
+  props[PROP_VELOCITY] =
+    g_param_spec_double ("velocity",
+                         "Velocity",
+                         "The current velocity of the animation",
+                         -G_MAXDOUBLE,
+                         G_MAXDOUBLE,
+                         0,
+                         G_PARAM_READABLE);
+
   g_object_class_install_properties (object_class, LAST_PROP, props);
 }
 
@@ -578,3 +609,11 @@ adw_spring_animation_get_estimated_duration (AdwSpringAnimation *self)
 
   return self->estimated_duration;
 }
+
+double
+adw_spring_animation_get_velocity (AdwSpringAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_SPRING_ANIMATION (self), 0);
+
+  return self->velocity;
+}
diff --git a/src/adw-spring-animation.h b/src/adw-spring-animation.h
index 0859eca3..d417629e 100644
--- a/src/adw-spring-animation.h
+++ b/src/adw-spring-animation.h
@@ -70,4 +70,7 @@ void     adw_spring_animation_set_clamp (AdwSpringAnimation *self,
 ADW_AVAILABLE_IN_ALL
 guint adw_spring_animation_get_estimated_duration (AdwSpringAnimation *self);
 
+ADW_AVAILABLE_IN_ALL
+double adw_spring_animation_get_velocity (AdwSpringAnimation *self);
+
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]