1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 4 -*-
*
* Copyright (C) 2011,2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Robert Ancell <robert.ancell@canonical.com>
* Michael Terry <michael.terry@canonical.com>
*/
namespace Animation {
public class AnimateTimer : Object {
public bool is_running { get { return timeout != 0; } }
public double progress { get; private set; }
/* speed is in milliseconds */
public int speed { get; set; }
public unowned EasingFunc easing_func { get; private set; }
/* progress is from 0.0 to 1.0 */
public signal void animate (double progress);
/* AnimateTimer requires two things: an easing function and a speed.
The speed is just the duration of the animation in milliseconds.
The easing function describes how fast the animation occurs at different
parts of the duration.
See http://hosted.zeh.com.br/tweener/docs/en-us/misc/transitions.html
for examples of various easing functions.
A few are provided with this class, notably ease_in_out and
ease_out_quint.
*/
/* speed is in milliseconds */
/* x and y are 0.0 to 1.0 */
public delegate double EasingFunc (double x);
private TimeSpan extra_time = 0;
private TimeSpan length = 0;
private TimeSpan start_time = 0;
private double extra_progress = 0.0;
private uint timeout = 0;
public AnimateTimer (EasingFunc func, int speed) {
Object (speed: speed);
this.easing_func = func;
}
~AnimateTimer () {
stop ();
}
/* temp_speed is in milliseconds */
public void reset (int temp_speed = -1) {
stop ();
timeout = Timeout.add (16, animate_cb);
progress = 0;
start_time = 0;
extra_time = 0;
extra_progress = 0;
if (temp_speed == -1)
temp_speed = speed;
length = temp_speed * TimeSpan.MILLISECOND;
}
public void stop () {
if (timeout != 0)
Source.remove (timeout);
timeout = 0;
}
private bool animate_cb () {
if (start_time == 0)
start_time = GLib.get_monotonic_time ();
var time_progress = normalize_time (GLib.get_monotonic_time ());
progress = calculate_progress (time_progress);
animate (progress);
if (time_progress >= 1.0) {
timeout = 0;
return false;
} else {
return true;
}
}
/* Returns 0.0 to 1.0 where 1.0 is at or past end_time */
private double normalize_time (TimeSpan now) {
if (length == 0)
return 1.0f;
return (((double)(now - start_time)) / length).clamp (0.0, 1.0);
}
/* Returns 0.0 to 1.0 where 1.0 is done.
time is not normalized yet! */
private double calculate_progress (double time_progress) {
var y = easing_func (time_progress);
return y.clamp (0.0, 1.0);
}
public static double ease_in_out (double x) {
return (1 - Math.cos (Math.PI * x)) / 2;
}
public static double ease_in_quad (double x) {
return Math.pow (x, 2);
}
public static double ease_out_quad (double x) {
return -1 * Math.pow (x - 1, 2) + 1;
}
public static double ease_in_quint (double x) {
return Math.pow (x, 5);
}
public static double ease_out_quint (double x) {
return Math.pow (x - 1, 5) + 1;
}
}
}
|