diff options
author | Alessandro Ghedini <al3xbio@gmail.com> | 2011-10-19 10:56:04 +0200 |
---|---|---|
committer | Alessandro Ghedini <al3xbio@gmail.com> | 2011-10-19 10:56:04 +0200 |
commit | 6451a495637c6e3047a5a56573cffc6e3de9a515 (patch) | |
tree | 7c3eb29532e7c4b36a9da13c5890664fb816959b /src/utilities/animatedValue.vala |
Imported Upstream version 0.2+gitdfdad95upstream/0.2+gitdfdad95
Diffstat (limited to 'src/utilities/animatedValue.vala')
-rw-r--r-- | src/utilities/animatedValue.vala | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/utilities/animatedValue.vala b/src/utilities/animatedValue.vala new file mode 100644 index 0000000..32ab889 --- /dev/null +++ b/src/utilities/animatedValue.vala @@ -0,0 +1,190 @@ +/* +Copyright (c) 2011 by Simon Schneegans + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the Free +Software Foundation, either version 3 of the License, or (at your option) +any later version. + +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/>. +*/ + +namespace GnomePie { + +///////////////////////////////////////////////////////////////////////// +/// A class which interpolates smoothly between to given values. +/// Duration and interpolation mode can be specified. +///////////////////////////////////////////////////////////////////////// + +public class AnimatedValue : GLib.Object { + + ///////////////////////////////////////////////////////////////////// + /// The direction of the interpolation. + ///////////////////////////////////////////////////////////////////// + + public enum Direction { IN, OUT, IN_OUT, OUT_IN } + + ///////////////////////////////////////////////////////////////////// + /// Type of the interpolation, linear or cubic. + ///////////////////////////////////////////////////////////////////// + + private enum Type { LINEAR, CUBIC } + + ///////////////////////////////////////////////////////////////////// + /// Current value, interpolated. + ///////////////////////////////////////////////////////////////////// + + public double val { get; private set; } + + ///////////////////////////////////////////////////////////////////// + /// Starting value of the interpolation. + ///////////////////////////////////////////////////////////////////// + + public double start { get; private set; default=0.0; } + + ///////////////////////////////////////////////////////////////////// + /// Final value of the interpolation. + ///////////////////////////////////////////////////////////////////// + + public double end { get; private set; default=0.0; } + + ///////////////////////////////////////////////////////////////////// + /// The current state. In range 0 .. 1 + ///////////////////////////////////////////////////////////////////// + + private double state = 0.0; + + ///////////////////////////////////////////////////////////////////// + /// Duration of the interpolation. Should be in the same unit as + /// taken for the update() method. + ///////////////////////////////////////////////////////////////////// + + private double duration = 0.0; + + ///////////////////////////////////////////////////////////////////// + /// The amount of over-shooting of the cubicly interpolated value. + ///////////////////////////////////////////////////////////////////// + + private double multiplier = 0.0; + + ///////////////////////////////////////////////////////////////////// + /// Type of the interpolation, linear or cubic. + ///////////////////////////////////////////////////////////////////// + + private Type type = Type.LINEAR; + + ///////////////////////////////////////////////////////////////////// + /// The direction of the interpolation. + ///////////////////////////////////////////////////////////////////// + + private Direction direction = Direction.IN; + + ///////////////////////////////////////////////////////////////////// + /// Creates a new linearly interpolated value. + ///////////////////////////////////////////////////////////////////// + + public AnimatedValue.linear(double start, double end, double duration) { + this.val = start; + this.start = start; + this.end = end; + this.duration = duration; + } + + ///////////////////////////////////////////////////////////////////// + /// Creates a new cubicly interpolated value. + ///////////////////////////////////////////////////////////////////// + + public AnimatedValue.cubic(Direction direction, double start, double end, double duration, double multiplier = 0) { + this.val = start; + this.start = start; + this.end = end; + this.duration = duration; + this.direction = direction; + this.type = Type.CUBIC; + this.multiplier = multiplier; + } + + ///////////////////////////////////////////////////////////////////// + /// Resets the final value of the interpolation to a new value. The + /// current state is taken for the beginning from now. + ///////////////////////////////////////////////////////////////////// + + public void reset_target(double end, double duration) { + this.start = this.val; + this.end = end; + this.duration = duration; + this.state = 0.0; + } + + ///////////////////////////////////////////////////////////////////// + /// Updates the interpolated value according to it's type. + ///////////////////////////////////////////////////////////////////// + + public void update(double time) { + this.state += time/this.duration; + + if (state < 1) { + + switch (this.type) { + case Type.LINEAR: + this.val = update_linear(); + break; + case Type.CUBIC: + switch (this.direction) { + case Direction.IN: + this.val = update_ease_in(); + return; + case Direction.OUT: + this.val = update_ease_out(); + return; + case Direction.IN_OUT: + this.val = update_ease_in_out(); + return; + case Direction.OUT_IN: + this.val = update_ease_out_in(); + return; + } + break; + } + } else if (this.val != this.end) { + this.val = this.end; + } + } + + ///////////////////////////////////////////////////////////////////// + /// The following equations are based on Robert Penner's easing + /// equations. See (http://www.robertpenner.com/easing/) and their + /// adaption by Zeh Fernando, Nate Chatellier and Arthur Debert for + /// the Tweener class. See (http://code.google.com/p/tweener/). + ///////////////////////////////////////////////////////////////////// + + private double update_linear(double t = this.state, double s = this.start, double e = this.end) { + return (s + t*(e - s)); + } + + private double update_ease_in(double t = this.state, double s = this.start, double e = this.end) { + return (s + (t*t*((multiplier+1)*t-multiplier))*(e - s)); + } + + private double update_ease_out(double t = this.state, double s = this.start, double e = this.end) { + return (s + ((t-1) * (t-1) * ((multiplier+1)*(t-1)+multiplier) + 1) * (e - s)); + } + + private double update_ease_in_out(double t = this.state, double s = this.start, double e = this.end) { + if (this.state < 0.5) return update_ease_in(t*2, s, e - (e-s)*0.5); + else return update_ease_out(t*2-1, s + (e-s)*0.5, e); + } + + private double update_ease_out_in(double t = this.state, double s = this.start, double e = this.end) { + if (this.state < 0.5) return update_ease_out(t*2, s, e - (e-s)*0.5); + else return update_ease_in(t*2-1, s + (e-s)*0.5, e); + } +} + +} |