Commit 36fc52d9 authored by Manuel Genovés's avatar Manuel Genovés
Browse files

Subclass timed-animation

Move the relevant code from animation to timed-animation
parent dd779176
......@@ -34,12 +34,6 @@ void adw_animation_target_set_value (AdwAnimationTarget *target,
typedef void (*AdwAnimationDoneCallback) (gpointer user_data);
typedef double (*AdwAnimationEasingFunc) (double t);
typedef enum {
ADW_ANIMATION_INTERPOLATOR_EASE_IN,
ADW_ANIMATION_INTERPOLATOR_EASE_OUT,
ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT,
} AdwAnimationInterpolator;
typedef enum {
ADW_ANIMATION_STATUS_NONE,
ADW_ANIMATION_STATUS_COMPLETED,
......@@ -56,39 +50,20 @@ struct _AdwAnimationClass
{
GObjectClass parent_class;
gint64 (*estimate_duration) (AdwAnimation *self);
double (*calculate_value) (AdwAnimation *self, gint64 t);
guint (*estimate_duration) (AdwAnimation *self);
double (*calculate_value) (AdwAnimation *self, guint t);
/*< private >*/
gpointer padding[4];
};
AdwAnimation *adw_animation_new (GtkWidget *widget,
double from,
double to,
gint64 duration,
AdwAnimationTargetFunc value_cb,
gpointer user_data) G_GNUC_WARN_UNUSED_RESULT;
GtkWidget *adw_animation_get_widget (AdwAnimation *self);
double adw_animation_get_value (AdwAnimation *self);
double adw_animation_get_value_from (AdwAnimation *self);
void adw_animation_set_value_from (AdwAnimation *self,
double value);
double adw_animation_get_value_to (AdwAnimation *self);
void adw_animation_set_value_to (AdwAnimation *self,
double value);
gint64 adw_animation_get_duration (AdwAnimation *self);
void adw_animation_set_duration (AdwAnimation *self,
gint64 duration);
AdwAnimationInterpolator adw_animation_get_interpolator (AdwAnimation *self);
void adw_animation_set_interpolator (AdwAnimation *self,
AdwAnimationInterpolator interpolator);
AdwAnimationTarget *adw_animation_get_target (AdwAnimation *self);
AdwAnimationStatus adw_animation_get_status (AdwAnimation *self);
......
......@@ -86,7 +86,7 @@ adw_get_enable_animations (GtkWidget *widget)
{
gboolean enable_animations = TRUE;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
g_object_get (gtk_widget_get_settings (widget),
"gtk-enable-animations", &enable_animations,
......
......@@ -17,15 +17,10 @@ typedef struct
double value;
double value_from;
double value_to;
gint64 duration; /* ms */
gint64 start_time; /* ms */
guint tick_cb_id;
gulong unmap_cb_id;
AdwAnimationInterpolator interpolator;
AdwAnimationTargetFunc value_cb;
AdwAnimationTarget *target;
gpointer user_data;
......@@ -39,10 +34,6 @@ enum {
PROP_0,
PROP_VALUE,
PROP_WIDGET,
PROP_VALUE_FROM,
PROP_VALUE_TO,
PROP_DURATION,
PROP_INTERPOLATOR,
PROP_TARGET,
PROP_STATUS,
LAST_PROP,
......@@ -74,22 +65,6 @@ adw_animation_get_property (GObject *object,
g_value_set_object (value, adw_animation_get_widget (self));
break;
case PROP_VALUE_FROM:
g_value_set_double (value, adw_animation_get_value_from (self));
break;
case PROP_VALUE_TO:
g_value_set_double (value, adw_animation_get_value_to (self));
break;
case PROP_DURATION:
g_value_set_int64 (value, adw_animation_get_duration (self));
break;
case PROP_INTERPOLATOR:
g_value_set_enum (value, adw_animation_get_interpolator (self));
break;
case PROP_TARGET:
g_value_set_object (value, adw_animation_get_target (self));
break;
......@@ -117,22 +92,6 @@ adw_animation_set_property (GObject *object,
g_set_object (&priv->widget, g_value_get_object (value));
break;
case PROP_VALUE_FROM:
adw_animation_set_value_from (self, g_value_get_double (value));
break;
case PROP_VALUE_TO:
adw_animation_set_value_to (self, g_value_get_double (value));
break;
case PROP_DURATION:
adw_animation_set_duration (self, g_value_get_int64 (value));
break;
case PROP_INTERPOLATOR:
adw_animation_set_interpolator (self, g_value_get_enum (value));
break;
case PROP_TARGET:
g_set_object (&priv->target, g_value_get_object (value));
break;
......@@ -146,54 +105,17 @@ adw_animation_set_property (GObject *object,
}
}
static gint64
static guint
adw_animation_estimate_duration (AdwAnimation *self)
{
AdwAnimationPrivate *priv = adw_animation_get_instance_private (self);
return priv->duration;
return 0;
}
static double
adw_animation_calculate_value (AdwAnimation *self,
gint64 t)
guint t)
{
AdwAnimationPrivate *priv = adw_animation_get_instance_private (self);
double value;
gint64 duration = adw_animation_estimate_duration (self);
if (duration == 0)
{
if (t == 0)
return priv->value_from;
else
return priv->value_to;
}
if (t == duration)
return priv->value_to;
double iptr;
double mapped_duration = modf(((double) t / duration), &iptr);
g_print("%li\t%li\t%f\n", t, duration, mapped_duration);
switch (priv->interpolator) {
case ADW_ANIMATION_INTERPOLATOR_EASE_IN:
value = adw_ease_in_cubic (mapped_duration);
break;
case ADW_ANIMATION_INTERPOLATOR_EASE_OUT:
value = adw_ease_out_cubic (mapped_duration);
break;
case ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT:
value = adw_ease_in_out_cubic (mapped_duration);
break;
default:
g_assert_not_reached ();
}
return adw_lerp (priv->value_from, priv->value_to, value);
return 0.0;
}
static void
......@@ -214,9 +136,8 @@ adw_animation_constructed (GObject *object)
AdwAnimationPrivate *priv = adw_animation_get_instance_private (self);
G_OBJECT_CLASS (adw_animation_parent_class)->constructed (object);
priv->value = adw_animation_calculate_value (self, 0);
priv->value = ADW_ANIMATION_GET_CLASS (self)->calculate_value (self, 0);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE]);
}
static void
......@@ -247,41 +168,6 @@ adw_animation_class_init (AdwAnimationClass *klass)
GTK_TYPE_WIDGET,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
props[PROP_VALUE_FROM] =
g_param_spec_double ("value-from",
"Initial value",
"Initial value of the animation",
-G_MAXDOUBLE,
G_MAXDOUBLE,
0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
props[PROP_VALUE_TO] =
g_param_spec_double ("value-to",
"Final value",
"Final value of the animation",
-G_MAXDOUBLE,
G_MAXDOUBLE,
0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
props[PROP_DURATION] =
g_param_spec_int64 ("duration",
"Duration",
"Duration of the animation",
0,
G_MAXINT64,
0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
props[PROP_INTERPOLATOR] =
g_param_spec_enum ("interpolator",
"Interpolator",
"Easing function used in the animation",
ADW_TYPE_ANIMATION_INTERPOLATOR,
ADW_ANIMATION_INTERPOLATOR_EASE_OUT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
props[PROP_TARGET] =
g_param_spec_object ("target",
"Target",
......@@ -336,13 +222,13 @@ tick_cb (GtkWidget *widget,
AdwAnimationPrivate *priv = adw_animation_get_instance_private (self);
gint64 frame_time = gdk_frame_clock_get_frame_time (frame_clock) / 1000; /* ms */
gint64 duration = adw_animation_estimate_duration(self);
gint64 t = (double) (frame_time - priv->start_time);
guint duration = ADW_ANIMATION_GET_CLASS (self)->estimate_duration (self);
guint t = (guint) (frame_time - priv->start_time);
if (t >= duration && duration > 0) {
if (t >= duration && duration != ADW_DURATION_INFINITE) {
priv->tick_cb_id = 0;
set_value (self, adw_animation_calculate_value (self, duration));
set_value (self, ADW_ANIMATION_GET_CLASS (self)->calculate_value (self, duration));
if (priv->unmap_cb_id) {
g_signal_handler_disconnect (priv->widget, priv->unmap_cb_id);
......@@ -354,16 +240,13 @@ tick_cb (GtkWidget *widget,
return G_SOURCE_REMOVE;
}
set_value (self, adw_animation_calculate_value (self, t));
set_value (self, ADW_ANIMATION_GET_CLASS (self)->calculate_value (self, t));
return G_SOURCE_CONTINUE;
}
AdwAnimation *
adw_animation_new (GtkWidget *widget,
double from,
double to,
gint64 duration,
AdwAnimationTargetFunc target_func,
gpointer user_data)
{
......@@ -375,9 +258,6 @@ adw_animation_new (GtkWidget *widget,
target = adw_animation_target_new(target_func, user_data);
return g_object_new (ADW_TYPE_ANIMATION,
"widget", widget,
"value-from", from,
"value-to", to,
"duration", duration,
"target", target,
NULL);
}
......@@ -392,10 +272,13 @@ adw_animation_start (AdwAnimation *self)
priv = adw_animation_get_instance_private (self);
priv->status = ADW_ANIMATION_STATUS_RUNNING;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATUS]);
if (!adw_get_enable_animations (priv->widget) ||
!gtk_widget_get_mapped (priv->widget) ||
priv->duration <= 0) {
set_value (self, priv->value_to);
!gtk_widget_get_mapped (priv->widget)) {
guint duration = ADW_ANIMATION_GET_CLASS (self)->estimate_duration (self);
set_value (self, ADW_ANIMATION_GET_CLASS (self)->calculate_value (self, duration));
done (self);
......@@ -459,127 +342,6 @@ adw_animation_get_widget (AdwAnimation *self)
return priv->widget;
}
double
adw_animation_get_value_from (AdwAnimation *self)
{
AdwAnimationPrivate *priv;
g_return_val_if_fail (ADW_IS_ANIMATION (self), 0.0);
priv = adw_animation_get_instance_private (self);
return priv->value_from;
}
void
adw_animation_set_value_from (AdwAnimation *self,
double value)
{
AdwAnimationPrivate *priv;
g_return_if_fail (ADW_IS_ANIMATION (self));
priv = adw_animation_get_instance_private (self);
if (priv->value_from == value)
return;
priv->value_from = value;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE_FROM]);
}
double
adw_animation_get_value_to (AdwAnimation *self)
{
AdwAnimationPrivate *priv;
g_return_val_if_fail (ADW_IS_ANIMATION (self), 0.0);
priv = adw_animation_get_instance_private (self);
return priv->value_to;
}
void
adw_animation_set_value_to (AdwAnimation *self,
double value)
{
AdwAnimationPrivate *priv;
g_return_if_fail (ADW_IS_ANIMATION (self));
priv = adw_animation_get_instance_private (self);
if (priv->value_to == value)
return;
priv->value_to = value;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE_TO]);
}
gint64
adw_animation_get_duration (AdwAnimation *self)
{
AdwAnimationPrivate *priv;
g_return_val_if_fail (ADW_IS_ANIMATION (self), 0);
priv = adw_animation_get_instance_private (self);
return priv->duration;
}
void
adw_animation_set_duration (AdwAnimation *self,
gint64 duration)
{
AdwAnimationPrivate *priv;
g_return_if_fail (ADW_IS_ANIMATION (self));
priv = adw_animation_get_instance_private (self);
if (priv->duration == duration)
return;
priv->duration = duration;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DURATION]);
}
AdwAnimationInterpolator
adw_animation_get_interpolator (AdwAnimation *self)
{
AdwAnimationPrivate *priv;
g_return_val_if_fail (ADW_IS_ANIMATION (self), ADW_ANIMATION_INTERPOLATOR_EASE_OUT);
priv = adw_animation_get_instance_private (self);
return priv->interpolator;
}
void
adw_animation_set_interpolator (AdwAnimation *self,
AdwAnimationInterpolator interpolator)
{
AdwAnimationPrivate *priv;
g_return_if_fail (ADW_IS_ANIMATION (self));
g_return_if_fail (interpolator <= ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT);
priv = adw_animation_get_instance_private (self);
if (priv->interpolator == interpolator)
return;
priv->interpolator = interpolator;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INTERPOLATOR]);
}
AdwAnimationTarget *
adw_animation_get_target (AdwAnimation *self)
{
......
......@@ -17,8 +17,11 @@
G_BEGIN_DECLS
#define ADW_DURATION_INFINITE G_MAXUINT
#define ADW_TYPE_ANIMATION (adw_animation_get_type())
ADW_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (AdwAnimation, adw_animation, ADW, ANIMATION, GObject)
ADW_AVAILABLE_IN_ALL
......
......@@ -16,13 +16,13 @@ struct _AdwTimedAnimation
{
AdwAnimation parent_instance;
int repetitions;
int repeat_count;
gboolean reverse;
gboolean alternate;
double value_from;
double value_to;
gint64 duration; /* ms */
guint duration; /* ms */
gint64 start_time; /* ms */
......@@ -34,7 +34,7 @@ G_DEFINE_TYPE (AdwTimedAnimation, adw_timed_animation, ADW_TYPE_ANIMATION)
enum {
PROP_0,
PROP_REPETITIONS,
PROP_REPEAT_COUNT,
PROP_REVERSE,
PROP_ALTERNATE,
PROP_VALUE_FROM,
......@@ -46,62 +46,54 @@ enum {
static GParamSpec *props[LAST_PROP];
static gint64
static guint
adw_timed_animation_estimate_duration (AdwAnimation *animation)
{
AdwTimedAnimation *self = ADW_TIMED_ANIMATION (animation);
gint64 period_duration = adw_timed_animation_get_duration (self);
if (self->repeat_count == -1)
return ADW_DURATION_INFINITE;
if (period_duration == -1)
return period_duration;
return period_duration * adw_timed_animation_get_repetitions (self);
return self->duration * adw_timed_animation_get_repetitions (self);
}
static double
adw_timed_animation_calculate_value (AdwAnimation *animation,
gint64 t)
guint t)
{
AdwTimedAnimation *self = ADW_TIMED_ANIMATION (animation);
double value;
gint64 duration = adw_timed_animation_get_duration (self);
double mapped_duration;
double value_from = adw_timed_animation_get_value_from (self);
double value_to = adw_timed_animation_get_value_to (self);
double iteration;
double float_time;
gboolean reverse = false;
if (duration == 0)
if (self->duration == 0)
{
if (t == 0)
return value_from;
else
return value_to;
return self->value_to;
}
if (t == duration)
return value_to;
double repetition;
double float_time;
float_time = modf(((double) t / duration), &repetition);
float_time = modf(((double) t / self->duration), &iteration);
int direction;
if (self->alternate)
reverse = ((int) iteration % 2);
if (adw_timed_animation_get_alternate (self))
direction = ((int) repetition % 2) ? -1 : 1;
else
direction = 1;
if (self->reverse)
reverse = !reverse;
if (adw_timed_animation_get_reverse (self))
direction *= -1;
/* When the animation ends, return the exact final value, which depends on the
direction the animation is going at that moment, having into account that at the
time of this check we're already on the next iteration. */
if (t == adw_timed_animation_estimate_duration (animation))
{
return self->alternate == reverse ? self->value_to : self->value_from;
}
if (direction == 1)
mapped_duration = float_time;
else if (direction == -1)
mapped_duration = 1 - float_time;
mapped_duration = reverse ? 1 - float_time : float_time;
switch (self->interpolator) {
case ADW_TIMED_ANIMATION_INTERPOLATOR_EASE_IN:
......@@ -117,7 +109,7 @@ adw_timed_animation_calculate_value (AdwAnimation *animation,
g_assert_not_reached ();
}
return adw_lerp (value_from, value_to, value);
return adw_lerp (self->value_from, self->value_to, value);
}
static void
......@@ -129,7 +121,7 @@ adw_timed_animation_get_property (GObject *object,
AdwTimedAnimation *self = ADW_TIMED_ANIMATION (object);
switch (prop_id) {
case PROP_REPETITIONS:
case PROP_REPEAT_COUNT:
g_value_set_int (value, adw_timed_animation_get_repetitions (self));
break;
......@@ -150,7 +142,7 @@ adw_timed_animation_get_property (GObject *object,
break;
case PROP_DURATION:
g_value_set_int64 (value, adw_timed_animation_get_duration (self));
g_value_set_uint (value, adw_timed_animation_get_duration (self));
break;
case PROP_INTERPOLATOR:
......@@ -171,7 +163,7 @@ adw_timed_animation_set_property (GObject *object,
AdwTimedAnimation *self = ADW_TIMED_ANIMATION (object);
switch (prop_id) {
case PROP_REPETITIONS:
case PROP_REPEAT_COUNT:
adw_timed_animation_set_repetitions (self, g_value_get_int (value));
break;
......@@ -192,7 +184,7 @@ adw_timed_animation_set_property (GObject *object,
break;
case PROP_DURATION:
adw_timed_animation_set_duration (self, g_value_get_int64 (value));
adw_timed_animation_set_duration (self, g_value_get_uint (value));
break;
case PROP_INTERPOLATOR:
......@@ -217,13 +209,13 @@ adw_timed_animation_class_init (AdwTimedAnimationClass *klass)
animation_class->calculate_value = adw_timed_animation_calculate_value;
props[PROP_REPETITIONS] =
g_param_spec_int ("repetitions",
"Repetitions",
"Number of times the animation should play. Set -1 for a looped animation",
-1, G_MAXINT,
1,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
props[PROP_REPEAT_COUNT] =
g_param_spec_int ("repeat-count",
"Repeat count",
"Number of times the animation should play. Set -1 for a looped animation",
-1, G_MAXINT,
1,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
props[PROP_REVERSE] =
g_param_spec_boolean ("reverse",
......@@ -258,13 +250,13 @@ adw_timed_animation_class_init (AdwTimedAnimationClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
props[PROP_DURATION] =
g_param_spec_int64 ("duration",
"Duration",
"Duration of the animation",
0,