[gnome-js-common] Add lang, signals, and tweener modules



commit 641291e8ac09524eabc92a1f71619b7f4abfbbef
Author: Robert Carr <racarr svn gnome org>
Date:   Thu May 14 00:46:32 2009 -0400

    Add lang, signals, and tweener modules
---
 Makefile.am                  |    2 +-
 configure.ac                 |    2 +
 modules/lang.js              |  112 ++++++
 modules/signals.js           |  146 +++++++
 modules/tweener/Makefile.am  |    6 +
 modules/tweener/equations.js |  650 ++++++++++++++++++++++++++++++++
 modules/tweener/tweenList.js |  111 ++++++
 modules/tweener/tweener.js   |  856 ++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 1884 insertions(+), 1 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index eeac865..1f02d70 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = po
+SUBDIRS = po modules
 
 gnome_js_commondocdir = ${prefix}/doc/gnome_js_common
 gnome_js_commondoc_DATA = \
diff --git a/configure.ac b/configure.ac
index 9d98e77..5bf616f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -48,6 +48,8 @@ fi
 AC_OUTPUT([
 Makefile
 po/Makefile.in
+modules/Makefile
+modules/tweener/Makefile
 ])
 
 echo "
diff --git a/modules/lang.js b/modules/lang.js
new file mode 100644
index 0000000..ccfa5b7
--- /dev/null
+++ b/modules/lang.js
@@ -0,0 +1,112 @@
+// Copyright (c) 2008  litl, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+// Utilities that are "meta-language" things like manipulating object props
+
+function countProperties(obj) {
+    var count = 0;
+    for (var property in obj) {
+        count += 1;
+    }
+    return count;
+}
+
+function _copyProperty(source, dest, property) {
+    var getterFunc = source.__lookupGetter__(property);
+    var setterFunc = source.__lookupSetter__(property);
+
+    if (getterFunc) {
+        dest.__defineGetter__(property, getterFunc);
+    }
+
+    if (setterFunc) {
+        dest.__defineSetter__(property, setterFunc);
+    }
+
+    if (!setterFunc && !getterFunc) {
+        dest[property] = source[property];
+    }
+}
+
+function copyProperties(source, dest) {
+    for (var property in source) {
+        _copyProperty(source, dest, property);
+    }
+}
+
+function copyPublicProperties(source, dest) {
+    for (var property in source) {
+        if (typeof(property) == 'string' &&
+            property.substring(0, 1) == '_') {
+            continue;
+        } else {
+            _copyProperty(source, dest, property);
+        }
+    }
+}
+
+function copyPropertiesNoOverwrite(source, dest) {
+    for (var property in source) {
+        if (!(property in dest)) {
+            _copyProperty(source, dest, property);
+        }
+    }
+}
+
+function removeNullProperties(obj) {
+    for (var property in obj) {
+        if (obj[property] == null)
+            delete obj[property];
+        else if (typeof(obj[property]) == 'object')
+            removeNullProperties(obj[property]);
+    }
+}
+
+/**
+ * Binds obj to callback. Makes it possible to refer to "obj"
+ * using this within the callback.
+ * @param {object} obj the object to bind
+ * @param {function} callback callback to bind obj in
+ * @param arguments additional arguments to the callback
+ * @returns: a new callback
+ * @type: function
+ */
+function bind(obj, callback) {
+    var me = obj;
+    var bindArguments = Array.prototype.slice.call(arguments, 2);
+
+    if (typeof(obj) != 'object') {
+        throw new Error(
+            "first argument to Lang.bind() must be an object, not " +
+                typeof(obj));
+    }
+
+    if (typeof(callback) != 'function') {
+        throw new Error(
+            "second argument to Lang.bind() must be a function, not " +
+                typeof(callback));
+    }
+
+    return function() {
+        var args = Array.prototype.slice.call(arguments);
+        args = args.concat(bindArguments);
+        return callback.apply(me, args);
+    };
+}
diff --git a/modules/signals.js b/modules/signals.js
new file mode 100644
index 0000000..0e16d82
--- /dev/null
+++ b/modules/signals.js
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2008  litl, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+// A couple principals of this simple signal system:
+// 1) should look just like our GObject signal binding
+// 2) memory and safety matter more than speed of connect/disconnect/emit
+// 3) the expectation is that a given object will have a very small number of
+//    connections, but they may be to different signal names
+
+function _connect(name, callback) {
+    // be paranoid about callback arg since we'd start to throw from emit()
+    // if it was messed up
+    if (typeof(callback) != 'function')
+        throw new Error("When connecting signal must give a callback that is a function");
+
+    // we instantiate the "signal machinery" only on-demand if anything
+    // gets connected.
+    if (!('_signalConnections' in this)) {
+        this._signalConnections = [];
+        this._nextConnectionId = 1;
+    }
+
+    var id = this._nextConnectionId;
+    this._nextConnectionId += 1;
+
+    // this makes it O(n) in total connections to emit, but I think
+    // it's right to optimize for low memory and reentrancy-safety
+    // rather than speed
+    this._signalConnections.push({ 'id' : id,
+                                   'name' : name,
+                                   'callback' : callback,
+                                   'disconnected' : false
+                                 });
+    return id;
+}
+
+function _disconnect(id) {
+    if ('_signalConnections' in this) {
+        var i;
+        var length = this._signalConnections.length;
+        for (i = 0; i < length; ++i) {
+            var connection = this._signalConnections[i];
+            if (connection.id == id) {
+                if (connection.disconnected)
+                    throw new Error("Signal handler id " + id + " already disconnected");
+
+                // set a flag to deal with removal during emission
+                connection.disconnected = true;
+                this._signalConnections.splice(i, 1);
+
+                return;
+            }
+        }
+    }
+    throw new Error("No signal connection " + id + " found");
+}
+
+function _disconnectAll() {
+    if ('_signalConnections' in this) {
+        while (this._signalConnections.length > 0) {
+            _disconnect.call(this, this._signalConnections[0].id);
+        }
+    }
+}
+
+function _emit(name /* , arg1, arg2 */) {
+    // may not be any signal handlers at all, if not then return
+    if (!('_signalConnections' in this))
+        return;
+
+    // To deal with re-entrancy (removal/addition while
+    // emitting), we copy out a list of what was connected
+    // at emission start; and just before invoking each
+    // handler we check its disconnected flag.
+    var handlers = [];
+    var i;
+    var length = this._signalConnections.length;
+    for (i = 0; i < length; ++i) {
+        var connection = this._signalConnections[i];
+        if (connection.name == name) {
+            handlers.push(connection);
+        }
+    }
+
+    // create arg array which is emitter + everything passed in except
+    // signal name. Would be more convenient not to pass emitter to
+    // the callback, but trying to be 100% consistent with GObject
+    // which does pass it in. Also if we pass in the emitter here,
+    // people don't create closures with the emitter in them,
+    // which would be a cycle.
+
+    var arg_array = [ this ];
+    // arguments[0] should be signal name so skip it
+    length = arguments.length;
+    for (i = 1; i < length; ++i) {
+        arg_array.push(arguments[i]);
+    }
+
+    length = handlers.length;
+    for (i = 0; i < length; ++i) {
+        var connection = handlers[i];
+        if (!connection.disconnected) {
+            try {
+                // since we pass "null" for this, the global object will be used.
+                var ret = connection.callback.apply(null, arg_array);
+
+                // if the callback returns true, we don't call the next
+                // signal handlers
+                if (ret === true) {
+                    break;
+                }
+            } catch(e) {
+                // just log any exceptions so that callbacks can't disrupt
+                // signal emission
+                logError(e, "Exception in callback for signal: "+name);
+            }
+        }
+    }
+}
+
+function addSignalMethods(proto) {
+    proto.connect = _connect;
+    proto.disconnect = _disconnect;
+    proto.emit = _emit;
+    // this one is not in GObject, but useful
+    proto.disconnectAll = _disconnectAll;
+}
diff --git a/modules/tweener/Makefile.am b/modules/tweener/Makefile.am
new file mode 100644
index 0000000..b5a2155
--- /dev/null
+++ b/modules/tweener/Makefile.am
@@ -0,0 +1,6 @@
+tweenerdir=$(libdir)/gnome-js/tweener
+tweener_DATA= \
+	equations.js \
+	tweener.js \
+	tweenList.js
+
diff --git a/modules/tweener/equations.js b/modules/tweener/equations.js
new file mode 100644
index 0000000..e34ee29
--- /dev/null
+++ b/modules/tweener/equations.js
@@ -0,0 +1,650 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/* Copyright 2008 litl, LLC. All Rights Reserved. */
+/**
+ * Equations
+ * Main equations for the Tweener class
+ *
+ * @author              Zeh Fernando, Nate Chatellier
+ * @version             1.0.2
+ */
+
+/*
+ Disclaimer for Robert Penner's Easing Equations license:
+
+ TERMS OF USE - EASING EQUATIONS
+
+ Open source under the BSD License.
+
+ 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 written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+//log("Loading equations.js");
+
+// ==================================================================================================================================
+// TWEENING EQUATIONS functions -----------------------------------------------------------------------------------------------------
+// (the original equations are Robert Penner's work as mentioned on the disclaimer)
+
+/**
+ * Easing equation function for a simple linear tweening, with no easing.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeNone (t, b, c, d, p_params) {
+    return c*t/d + b;
+}
+
+/* Useful alias */
+function linear (t, b, c ,d, p_params) {
+    return easeNone (t, b, c, d, p_params);
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInQuad (t, b, c, d, p_params) {
+    return c*(t/=d)*t + b;
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutQuad (t, b, c, d, p_params) {
+    return -c *(t/=d)*(t-2) + b;
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInOutQuad (t, b, c, d, p_params) {
+    if ((t/=d/2) < 1) return c/2*t*t + b;
+    return -c/2 * ((--t)*(t-2) - 1) + b;
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutInQuad (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutQuad (t*2, b, c/2, d, p_params);
+    return easeInQuad((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInCubic (t, b, c, d, p_params) {
+    return c*(t/=d)*t*t + b;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutCubic (t, b, c, d, p_params) {
+    return c*((t=t/d-1)*t*t + 1) + b;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInOutCubic (t, b, c, d, p_params) {
+    if ((t/=d/2) < 1) return c/2*t*t*t + b;
+    return c/2*((t-=2)*t*t + 2) + b;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutInCubic (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutCubic (t*2, b, c/2, d, p_params);
+    return easeInCubic((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInQuart (t, b, c, d, p_params) {
+    return c*(t/=d)*t*t*t + b;
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutQuart (t, b, c, d, p_params) {
+    return -c * ((t=t/d-1)*t*t*t - 1) + b;
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInOutQuart (t, b, c, d, p_params) {
+    if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
+    return -c/2 * ((t-=2)*t*t*t - 2) + b;
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutInQuart (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutQuart (t*2, b, c/2, d, p_params);
+    return easeInQuart((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInQuint (t, b, c, d, p_params) {
+    return c*(t/=d)*t*t*t*t + b;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutQuint (t, b, c, d, p_params) {
+    return c*((t=t/d-1)*t*t*t*t + 1) + b;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInOutQuint (t, b, c, d, p_params) {
+    if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
+    return c/2*((t-=2)*t*t*t*t + 2) + b;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutInQuint (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutQuint (t*2, b, c/2, d, p_params);
+    return easeInQuint((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInSine (t, b, c, d, p_params) {
+    return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutSine (t, b, c, d, p_params) {
+    return c * Math.sin(t/d * (Math.PI/2)) + b;
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInOutSine (t, b, c, d, p_params) {
+    return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutInSine (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutSine (t*2, b, c/2, d, p_params);
+    return easeInSine((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInExpo (t, b, c, d, p_params) {
+    return (t<=0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutExpo (t, b, c, d, p_params) {
+    return (t>=d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInOutExpo (t, b, c, d, p_params) {
+    if (t<=0) return b;
+    if (t>=d) return b+c;
+    if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+    return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutInExpo (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutExpo (t*2, b, c/2, d, p_params);
+    return easeInExpo((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInCirc (t, b, c, d, p_params) {
+    return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutCirc (t, b, c, d, p_params) {
+    return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInOutCirc (t, b, c, d, p_params) {
+    if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
+    return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutInCirc (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutCirc (t*2, b, c/2, d, p_params);
+    return easeInCirc((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @param a             Amplitude.
+ * @param p             Period.
+ * @return              The correct value.
+ */
+function easeInElastic (t, b, c, d, p_params) {
+    if (t<=0) return b;
+    if ((t/=d)>=1) return b+c;
+    var p = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period;
+    var s;
+    var a = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;
+    if (!Boolean(a) || a < Math.abs(c)) {
+        a = c;
+        s = p/4;
+    } else {
+        s = p/(2*Math.PI) * Math.asin (c/a);
+    }
+    return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @param a             Amplitude.
+ * @param p             Period.
+ * @return              The correct value.
+ */
+function easeOutElastic (t, b, c, d, p_params) {
+    if (t<=0) return b;
+    if ((t/=d)>=1) return b+c;
+    var p = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period;
+    var s;
+    var a = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;
+    if (!Boolean(a) || a < Math.abs(c)) {
+        a = c;
+        s = p/4;
+    } else {
+        s = p/(2*Math.PI) * Math.asin (c/a);
+    }
+    return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b);
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @param a             Amplitude.
+ * @param p             Period.
+ * @return              The correct value.
+ */
+function easeInOutElastic (t, b, c, d, p_params) {
+    if (t<=0) return b;
+    if ((t/=d/2)>=2) return b+c;
+    var p = !Boolean(p_params) || isNaN(p_params.period) ? d*(.3*1.5) : p_params.period;
+    var s;
+    var a = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;
+    if (!Boolean(a) || a < Math.abs(c)) {
+        a = c;
+        s = p/4;
+    } else {
+        s = p/(2*Math.PI) * Math.asin (c/a);
+    }
+    if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+    return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @param a             Amplitude.
+ * @param p             Period.
+ * @return              The correct value.
+ */
+function easeOutInElastic (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutElastic (t*2, b, c/2, d, p_params);
+    return easeInElastic((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @param s             Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return              The correct value.
+ */
+function easeInBack (t, b, c, d, p_params) {
+    var s = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;
+    return c*(t/=d)*t*((s+1)*t - s) + b;
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @param s             Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return              The correct value.
+ */
+function easeOutBack (t, b, c, d, p_params) {
+    var s = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;
+    return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @param s             Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return              The correct value.
+ */
+function easeInOutBack (t, b, c, d, p_params) {
+    var s = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;
+    if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
+    return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @param s             Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return              The correct value.
+ */
+function easeOutInBack (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutBack (t*2, b, c/2, d, p_params);
+    return easeInBack((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInBounce (t, b, c, d, p_params) {
+    return c - easeOutBounce (d-t, 0, c, d) + b;
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutBounce (t, b, c, d, p_params) {
+    if ((t/=d) < (1/2.75)) {
+        return c*(7.5625*t*t) + b;
+    } else if (t < (2/2.75)) {
+        return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
+    } else if (t < (2.5/2.75)) {
+        return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
+    } else {
+        return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
+    }
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeInOutBounce (t, b, c, d, p_params) {
+    if (t < d/2) return easeInBounce (t*2, 0, c, d) * .5 + b;
+    else return easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t             Current time (in frames or seconds).
+ * @param b             Starting value.
+ * @param c             Change needed in value.
+ * @param d             Expected easing duration (in frames or seconds).
+ * @return              The correct value.
+ */
+function easeOutInBounce (t, b, c, d, p_params) {
+    if (t < d/2) return easeOutBounce (t*2, b, c/2, d, p_params);
+    return easeInBounce((t*2)-d, b+c/2, c/2, d, p_params);
+}
+
+//log("Done loading equations.js");
diff --git a/modules/tweener/tweenList.js b/modules/tweener/tweenList.js
new file mode 100644
index 0000000..49c51af
--- /dev/null
+++ b/modules/tweener/tweenList.js
@@ -0,0 +1,111 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/* Copyright 2008 litl, LLC. All Rights Reserved. */
+/**
+ * The tween list object. Stores all of the properties and information that pertain to individual tweens.
+ *
+ * @author              Nate Chatellier, Zeh Fernando
+ * @version             1.0.4
+ * @private
+ */
+/*
+Licensed under the MIT License
+
+Copyright (c) 2006-2007 Zeh Fernando and Nate Chatellier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+http://code.google.com/p/tweener/
+http://code.google.com/p/tweener/wiki/License
+*/
+//log("Loading tweenlist.js");
+
+function TweenList(scope, timeStart, timeComplete,
+                      useFrames, transition, transitionParams) {
+    this._init(scope, timeStart, timeComplete, useFrames, transition,
+               transitionParams);
+}
+
+TweenList.prototype = {
+    _init: function(scope, timeStart, timeComplete,
+                    userFrames, transition, transitionParams) {
+        this.scope = scope;
+        this.timeStart = timeStart;
+        this.timeComplete = timeComplete;
+        this.userFrames = userFrames;
+        this.transition = transition;
+        this.transitionParams = transitionParams;
+
+        /* Other default information */
+        this.properties = new Object();
+        this.isPaused = false;
+        this.timePaused = undefined;
+        this.isCaller = false;
+        this.updatesSkipped = 0;
+        this.timesCalled = 0;
+        this.skipUpdates = 0;
+        this.hasStarted = false;
+    },
+
+    clone: function(omitEvents) {
+        var tween = new TweenList(this.scope, this.timeStart, this.timeComplete, this.userFrames,
+                                  this.transition, this.transitionParams);
+        tween.properties = new Array();
+        for (var name in this.properties) {
+            tween.properties[name] = this.properties[name];
+        }
+        tween.skipUpdates = this.skipUpdates;
+        tween.updatesSkipped = this.updatesSkipped;
+
+        if (!omitEvents) {
+            tween.onStart = this.onStart;
+            tween.onUpdate = this.onUpdate;
+            tween.onComplete = this.onComplete;
+            tween.onOverwrite = this.onOverwrite;
+            tween.onError = this.onError;
+            tween.onStartParams = this.onStartParams;
+            tween.onUpdateParams = this.onUpdateParams;
+            tween.onCompleteParams = this.onCompleteParams;
+            tween.onOverwriteParams = this.onOverwriteParams;
+            tween.onStartScope = this.onStartScope;
+            tween.onUpdateScope = this.onUpdateScope;
+            tween.onCompleteScope = this.onCompleteScope;
+            tween.onOverwriteScope = this.onOverwriteScope;
+            tween.onErrorScope = this.onErrorScope;
+        }
+        tween.rounded = this.rounded;
+        tween.isPaused = this.isPaused;
+        tween.timePaused = this.timePaused;
+        tween.isCaller = this.isCaller;
+        tween.count = this.count;
+        tween.timesCalled = this.timesCalled;
+        tween.waitFrames = this.waitFrames;
+        tween.hasStarted = this.hasStarted;
+
+        return tween;
+    }
+};
+
+function makePropertiesChain(obj) {
+    /* Tweener has a bunch of code here to get all the properties of all
+     * the objects we inherit from (the objects in the 'base' property).
+     * I don't think that applies to JavaScript...
+     */
+    return obj;
+};
+
+//log("Done loading tweenlist.js");
diff --git a/modules/tweener/tweener.js b/modules/tweener/tweener.js
new file mode 100644
index 0000000..d46e009
--- /dev/null
+++ b/modules/tweener/tweener.js
@@ -0,0 +1,856 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/* Copyright 2008  litl, LLC. All Rights Reserved. */
+/**
+ * Tweener
+ * Transition controller for movieclips, sounds, textfields and other objects
+ *
+ * @author              Zeh Fernando, Nate Chatellier, Arthur Debert
+ * @version             1.31.71
+ */
+
+/*
+ Licensed under the MIT License
+
+ Copyright (c) 2006-2007 Zeh Fernando and Nate Chatellier
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ the Software, and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ http://code.google.com/p/tweener/
+ http://code.google.com/p/tweener/wiki/License
+ */
+
+//log("Loading tweener.js");
+
+const TweenList = imports.tweener.tweenList;
+const Mainloop = imports.mainloop;
+const Signals = imports.signals;
+
+var _inited = false;
+var _engineExists = false;
+var _transitionList = null;
+var _tweenList = null;
+
+var _timeScale = 1;
+
+var _specialPropertyList = [];
+var _specialPropertyModifierList = [];
+var _specialPropertySplitterList = [];
+
+/*
+ * Ticker should implement:
+ *
+ * property FRAME_RATE
+ * start()
+ * stop()
+ * getTime() gets time in milliseconds from start()
+ * signal prepare-frame
+ *
+ */
+var _ticker = null;
+
+var _prepareFrameId = 0;
+
+/* default frame ticker */
+function FrameTicker() {
+    this._init();
+}
+
+FrameTicker.prototype = {
+    FRAME_RATE: 65,
+
+    _init : function() {
+    },
+
+    start : function() {
+        this._currentTime = 0;
+
+        var me = this;
+        this._timeoutID =
+            Mainloop.timeout_add(Math.floor(1000 / me.FRAME_RATE),
+                                 function() {
+                                     me._currentTime += 1000 / me.FRAME_RATE;
+                                     me.emit('prepare-frame');
+                                     return true;
+                                 });
+    },
+
+    stop : function() {
+        if ('_timeoutID' in this) {
+            Mainloop.source_remove(this._timeoutID);
+            delete this._timeoutID;
+        }
+
+        this._currentTime = 0;
+    },
+
+    getTime : function() {
+        return this._currentTime;
+    }
+};
+Signals.addSignalMethods(FrameTicker.prototype);
+
+_ticker = new FrameTicker();
+
+/* TODOs:
+ *
+ * Special properties:
+ *
+ * Special properties are 'proxy' properties used in Tweener to tween
+ * (animate) things that are not proper properties per se. One example
+ * given is the 'frame' of an object in ActionScript, which is not an
+ * object property. Using the special property '_frame' you could animate
+ * it like this:
+ *
+ * Tweener.addTween(myMovieClip, {_frame:20, time:1});
+ *
+ * which would be equivalent to applying a fast-forward to it.
+ *
+ * This properties need a special support in the code, and I've removed it
+ * for now until we see the need for it in our clutter based stuff.
+ */
+
+/* This is a bit pointless now, but let's keep it anyway... */
+function _init() {
+    if (_inited)
+        return;
+
+    _inited = true;
+}
+
+function setFrameTicker(ticker) {
+    _ticker = ticker;
+}
+
+function _startEngine() {
+    if (_engineExists)
+        return;
+
+    _engineExists = true;
+    _tweenList = new Array();
+
+    if (!_ticker) {
+        throw new Error("Must call setFrameTicker()");
+    }
+
+    _prepareFrameId = _ticker.connect('prepare-frame',
+                                      _onEnterFrame);
+    _ticker.start();
+}
+
+function _stopEngine() {
+    if (!_engineExists)
+        return;
+
+    _engineExists = false;
+    _tweenList = false;
+
+    _ticker.disconnect(_prepareFrameId);
+    _prepareFrameId = 0;
+    _ticker.stop();
+}
+
+function _getCurrentTweeningTime(tweening) {
+    return _ticker.getTime();
+}
+
+function _removeTweenByIndex(i) {
+    _tweenList[i] = null;
+
+    var finalRemoval = arguments[1];
+
+    if (finalRemoval != undefined && finalRemoval)
+        _tweenList.splice(i, 1);
+
+    return true;
+}
+
+function _resumeTweenByIndex(i) {
+    var tweening = _tweenList[i];
+
+    if (tweening == null || !tweening.isPaused)
+        return false;
+
+    var currentTime = _getCurrentTweeningTime(tweening);
+
+    tweening.timeStart += currentTime - tweening.timePaused;
+    tweening.timeComplete += currentTime - tweening.timePaused;
+    tweening.timePaused = undefined;
+    tweening.isPaused = false;
+
+    return true;
+};
+
+/* FIXME: any way to get the function name from the fn itself? */
+function _callOnFunction(fn, fnname, scope, fallbackScope, params)
+{
+    if (fn) {
+        var eventScope = scope ? scope : fallbackScope;
+        try {
+            fn.apply(eventScope, params);
+        } catch (e) {
+            logError(e, "Error calling " + fnname);
+        }
+    }
+}
+
+function _updateTweenByIndex(i) {
+    var tweening = _tweenList[i];
+
+    if (tweening == null || !tweening.scope)
+        return false;
+
+    var currentTime = _getCurrentTweeningTime(tweening);
+
+    if (currentTime < tweening.timeStart)
+        return true; // Hasn't started, so return true
+
+    var scope = tweening.scope;
+    var t, b, c, d, nv;
+
+    var isOver = false;
+
+    if (tweening.isCaller) {
+        do {
+            t = ((tweening.timeComplete - tweening.timeStart)/tweening.count) *
+                (tweening.timesCalled + 1);
+            b = tweening.timeStart;
+            c = tweening.timeComplete - tweening.timeStart;
+            d = tweening.timeComplete - tweening.timeStart;
+            nv = tweening.transition(t, b, c, d);
+
+            if (currentTime >= nv) {
+                _callOnFunction(tweening.onUpdate, "onUpdate", tweening.onUpdateScope,
+                                scope, tweening.onUpdateParams);
+
+                tweening.timesCalled++;
+                if (tweening.timesCalled >= tweening.count) {
+                    isOver = true;
+                    break;
+                }
+
+                if (tweening.waitFrames)
+                    break;
+            }
+        } while (currentTime >= nv);
+    } else {
+        var mustUpdate;
+
+        if (currentTime >= tweening.timeComplete) {
+            isOver = true;
+            mustUpdate = true;
+        } else {
+            mustUpdate = tweening.skipUpdates < 1 ||
+                !tweening.skipUpdates ||
+                tweening.updatesSkipped >= tweening.skipUpdates;
+        }
+
+        if (!tweening.hasStarted) {
+            _callOnFunction(tweening.onStart, "onStart", tweening.onStartScope,
+                            scope, tweening.onStartParams);
+
+            for (name in tweening.properties) {
+                var pv;
+
+                if (tweening.properties[name].isSpecialProperty) {
+                    // It's a special property, tunnel via the special property function
+                    if (_specialPropertyList[name].preProcess != undefined) {
+                        tweening.properties[name].valueComplete = _specialPropertyList[name].preProcess(scope, _specialPropertyList[name].parameters, tweening.properties[name].originalValueComplete, tweening.properties[name].extra);
+                    }
+                    pv = _specialPropertyList[name].getValue(scope, _specialPropertyList[name].parameters, tweening.properties[name].extra);
+                } else {
+                    // Directly read property
+                    pv = scope[name];
+                }
+                tweening.properties[name].valueStart = isNaN(pv) ? tweening.properties[name].valueComplete : pv;
+            }
+
+            mustUpdate = true;
+            tweening.hasStarted = true;
+        }
+
+        if (mustUpdate) {
+            for (name in tweening.properties) {
+                var property = tweening.properties[name];
+
+                if (isOver) {
+                    // Tweening time has finished, just set it to the final value
+                    nv = property.valueComplete;
+                } else {
+                    if (property.hasModifier) {
+                        // Modified
+                        t = currentTime - tweening.timeStart;
+                        d = tweening.timeComplete - tweening.timeStart;
+                        nv = tweening.transition(t, 0, 1, d, tweening.transitionParams);
+                        nv = property.modifierFunction(property.valueStart, property.valueComplete, nv, property.modifierParameters);
+                    } else {
+                        // Normal update
+                        t = currentTime - tweening.timeStart;
+                        b = property.valueStart;
+                        c = property.valueComplete - property.valueStart;
+                        d = tweening.timeComplete - tweening.timeStart;
+                        nv = tweening.transition(t, b, c, d, tweening.transitionParams);
+                    }
+                }
+
+                if (tweening.rounded)
+                    nv = Math.round(nv);
+
+                if (property.isSpecialProperty) {
+                    // It's a special property, tunnel via the special property method
+                    _specialPropertyList[name].setValue(scope, nv, _specialPropertyList[name].parameters, tweening.properties[name].extra);
+                } else {
+                    // Directly set property
+                    scope[name] = nv;
+                }
+            }
+
+            tweening.updatesSkipped = 0;
+
+            _callOnFunction(tweening.onUpdate, "onUpdate", tweening.onUpdateScope,
+                            scope, tweening.onUpdateParams);
+
+        } else {
+            tweening.updatesSkipped++;
+        }
+    }
+
+    if (isOver) {
+        _callOnFunction(tweening.onComplete, "onComplete", tweening.onCompleteScope,
+                        scope, tweening.onCompleteParams);
+    }
+
+    return !isOver;
+}
+
+function _updateTweens() {
+    if (_tweenList.length == 0)
+        return false;
+
+    for (var i = 0; i < _tweenList.length; i++) {
+        if (_tweenList[i] == undefined || !_tweenList[i].isPaused) {
+            if (!_updateTweenByIndex(i))
+                _removeTweenByIndex(i);
+
+            if (_tweenList[i] == null) {
+                _removeTweenByIndex(i, true);
+                i--;
+            }
+        }
+    }
+
+    return true;
+}
+
+/* Ran once every 'frame'. It's the main engine, updates all existing tweenings */
+function _onEnterFrame() {
+    if (!_updateTweens())
+        _stopEngine();
+
+    return true;
+};
+
+const restrictedWords = {
+    time: true,
+    delay: true,
+    userFrames: true,
+    skipUpdates: true,
+    transition: true,
+    transitionParams: true,
+    onStart: true,
+    onUpdate: true,
+    onComplete: true,
+    onOverwrite: true,
+    onError: true,
+    rounded: true,
+    onStartParams: true,
+    onUpdateParams: true,
+    onCompleteParams: true,
+    onOverwriteParams: true,
+    onStartScope: true,
+    onUpdateScope: true,
+    onCompleteScope: true,
+    onOverwriteScope: true,
+    onErrorScope: true
+};
+
+function _constructPropertyList(obj) {
+    var properties = new Object();
+    var modifiedProperties = new Object();
+
+    for (var istr in obj) {
+        if (restrictedWords[istr])
+            continue;
+
+        if (_specialPropertySplitterList[istr] != undefined) {
+            // Special property splitter
+            var splitProperties = _specialPropertySplitterList[istr].splitValues(obj[istr], _specialPropertySplitterList[istr].parameters);
+            for (var i = 0; i < splitProperties.length; i++) {
+                if (_specialPropertySplitterList[splitProperties[i].name] != undefined) {
+                    var splitProperties2 = _specialPropertySplitterList[splitProperties[i].name].splitValues(splitProperties[i].value, _specialPropertySplitterList[splitProperties[i].name].parameters);
+                    for (var j = 0; j < splitProperties2.length; j++) {
+                        properties[splitProperties2[j].name] = {
+			    valueStart: undefined,
+			    valueComplete: splitProperties2[j].value,
+			    arrayIndex: splitProperties2[j].arrayIndex,
+			    isSpecialProperty: false
+			};
+                    }
+                } else {
+                    properties[splitProperties[i].name] = {
+			valueStart: undefined,
+			valueComplete: splitProperties[i].value,
+			arrayIndex: splitProperties[i].arrayIndex,
+			isSpecialProperty: false
+		    };
+                }
+            }
+        } else if (_specialPropertyModifierList[istr] != undefined) {
+            // Special property modifier
+            var tempModifiedProperties = _specialPropertyModifierList[istr].modifyValues(obj[istr]);
+            for (var i = 0; i < tempModifiedProperties.length; i++) {
+                modifiedProperties[tempModifiedProperties[i].name] = {
+                    modifierParameters: tempModifiedProperties[i].parameters,
+                    modifierFunction: _specialPropertyModifierList[istr].getValue
+                };
+            }
+        } else {
+            properties[istr] = {
+                valueStart: undefined,
+                valueComplete: obj[istr]
+            };
+        }
+    }
+
+    // Adds the modifiers to the list of properties
+    for (istr in modifiedProperties) {
+        if (properties[istr]) {
+            properties[istr].modifierParameters = modifiedProperties[istr].modifierParameters;
+            properties[istr].modifierFunction = modifiedProperties[istr].modifierFunction;
+        }
+    }
+
+    return properties;
+}
+
+function PropertyInfo(valueStart, valueComplete, originalValueComplete,
+                      arrayIndex, extra, isSpecialProperty,
+                      modifierFunction, modifierParameters) {
+    this._init(valueStart, valueComplete, originalValueComplete,
+               arrayIndex, extra, isSpecialProperty,
+               modifierFunction, modifierParameters);
+}
+
+PropertyInfo.prototype = {
+    _init: function(valueStart, valueComplete, originalValueComplete,
+                    arrayIndex, extra, isSpecialProperty,
+                    modifierFunction, modifierParameters) {
+        this.valueStart             =       valueStart;
+        this.valueComplete          =       valueComplete;
+        this.originalValueComplete  =       originalValueComplete;
+        this.arrayIndex             =       arrayIndex;
+        this.extra                  =       extra;
+        this.isSpecialProperty      =       isSpecialProperty;
+        this.hasModifier            =       Boolean(modifierFunction);
+        this.modifierFunction       =       modifierFunction;
+        this.modifierParameters     =       modifierParameters;
+    }
+};
+
+function _addTweenOrCaller(target, tweeningParameters, isCaller) {
+    if (!target)
+        return false;
+
+    var scopes; // List of objects to tween
+    if (target instanceof Array) {
+        // The first argument is an array
+        scopes = target.concat(); // XXX: To copy the array I guess
+    } else {
+        // The first argument(s) is(are) object(s)
+        scopes = new Array(target);
+    }
+
+    var obj;
+
+    if (isCaller) {
+        obj = tweeningParameters;
+    } else {
+        obj = TweenList.makePropertiesChain(tweeningParameters);
+
+        var properties = _constructPropertyList(obj);
+
+        // Verifies whether the properties exist or not, for warning messages
+        for (istr in properties) {
+            if (_specialPropertyList[istr] != undefined) {
+                properties[istr].isSpecialProperty = true;
+            } else {
+                for (var i = 0; i < scopes.length; i++) {
+                    if (scopes[i][istr] == undefined)
+                        log("The property " + istr + " doesn't seem to be a normal object property of " + scopes[i] + " or a registered special property");
+                }
+            }
+        }
+    }
+
+    // Creates the main engine if it isn't active
+    if (!_inited) _init();
+    if (!_engineExists) _startEngine();
+
+    // Creates a "safer", more strict tweening object
+    var time = isNaN(obj.time) ? 0 : obj.time;
+    var delay = isNaN(obj.delay) ? 0 : obj.delay;
+
+    var transition;
+
+    // FIXME: Tweener allows you to use functions with an all lower-case name
+    if (typeof obj.transition == "string") {
+        transition = imports.tweener.equations[obj.transition];
+    } else {
+        transition = obj.transition;
+    }
+
+    if (!transition)
+        transition = imports.tweener.equations["easeOutExpo"];
+
+    var tween;
+
+    for (var i = 0; i < scopes.length; i++) {
+        if (!isCaller) {
+            // Make a copy of the properties
+            var copyProperties = new Object();
+            for (istr in properties) {
+                copyProperties[istr] = new PropertyInfo(properties[istr].valueStart,
+                                                        properties[istr].valueComplete,
+                                                        properties[istr].valueComplete,
+                                                        properties[istr].arrayIndex,
+                                                        {},
+                                                        properties[istr].isSpecialProperty,
+                                                        properties[istr].modifierFunction,
+                                                        properties[istr].modifierParameters);
+            }
+        }
+
+        tween = new TweenList.TweenList(scopes[i],
+                                        _ticker.getTime() + ((delay * 1000) / _timeScale),
+                                        _ticker.getTime() + (((delay * 1000) + (time * 1000)) / _timeScale),
+                                        false,
+                                        transition,
+                                        obj.transitionParams);
+
+        tween.properties               =       isCaller ? null : copyProperties;
+        tween.onStart                  =       obj.onStart;
+        tween.onUpdate                 =       obj.onUpdate;
+        tween.onComplete               =       obj.onComplete;
+        tween.onOverwrite              =       obj.onOverwrite;
+        tween.onError                  =       obj.onError;
+        tween.onStartParams            =       obj.onStartParams;
+        tween.onUpdateParams           =       obj.onUpdateParams;
+        tween.onCompleteParams         =       obj.onCompleteParams;
+        tween.onOverwriteParams        =       obj.onOverwriteParams;
+        tween.onStartScope             =       obj.onStartScope;
+        tween.onUpdateScope            =       obj.onUpdateScope;
+        tween.onCompleteScope          =       obj.onCompleteScope;
+        tween.onOverwriteScope         =       obj.onOverwriteScope;
+        tween.onErrorScope             =       obj.onErrorScope;
+        tween.rounded                  =       obj.rounded;
+        tween.skipUpdates              =       obj.skipUpdates;
+        tween.isCaller                 =       isCaller;
+
+        if (isCaller) {
+            tween.count = obj.count;
+            tween.waitFrames = obj.waitFrames;
+        }
+
+        if (!isCaller) {
+            // Remove other tweenings that occur at the same time
+            removeTweensByTime(tween.scope, tween.properties, tween.timeStart, tween.timeComplete);
+        }
+
+        // And finally adds it to the list
+        _tweenList.push(tween);
+
+        // Immediate update and removal if it's an immediate tween
+        // If not deleted, it executes at the end of this frame execution
+        if (time == 0 && delay == 0) {
+            var myT = _tweenList.length-1;
+            _updateTweenByIndex(myT);
+            _removeTweenByIndex(myT);
+        }
+    }
+
+    return true;
+};
+
+function addTween(target, tweeningParameters) {
+    return _addTweenOrCaller(target, tweeningParameters, false);
+};
+
+function addCaller(target, tweeningParameters) {
+    return _addTweenOrCaller(target, tweeningParameters, true);
+};
+
+function _getNumberOfProperties(object) {
+    var totalProperties = 0;
+
+    for (var name in object)
+        totalProperties ++;
+
+    return totalProperties;
+}
+
+function removeTweensByTime(scope, properties, timeStart, timeComplete) {
+    var removed = false;
+    var removedLocally;
+
+    for (var i = 0; i < _tweenList.length; i++) {
+        removedLocally = false;
+
+        if (_tweenList[i] &&
+            scope == _tweenList[i].scope &&
+            timeComplete > _tweenList[i].timeStart &&
+            timeStart < _tweenList[i].timeComplete) {
+
+            for (name in _tweenList[i].properties) {
+                if (properties[name]) {
+                    _callOnFunction(_tweenList[i].onOverwrite, "onOverwrite", _tweenList[i].onOverwriteScope,
+                                    _tweenList[i].scope, _tweenList[i].onOverwriteParams);
+
+                    _tweenList[i].properties[name] = undefined;
+                    delete _tweenList[i].properties[name];
+                    removedLocally = true;
+                    removed = true;
+                }
+            }
+
+            if (removedLocally &&
+                _getNumberOfProperties(_tweenList[i].properties) == 0) {
+                _removeTweenByIndex(i);
+            }
+        }
+    }
+
+    return removed;
+};
+
+function _pauseTweenByIndex(i) {
+    var tweening = _tweenList[i];
+
+    if (tweening == null || tweening.isPaused)
+        return false;
+
+    tweening.timePaused = _getCurrentTweeningTime(tweening);
+    tweening.isPaused = true;
+
+    return true;
+};
+
+function _splitTweens(tween, properties) {
+    var originalTween = _tweenList[tween];
+    var newTween = originalTween.clone();
+
+    for (var i = 0; i < properties.length; i++) {
+        var name = properties[i];
+        if (originalTween.properties[name]) {
+            originalTween.properties[name] = undefined;
+            delete originalTween.properties[name];
+        }
+    }
+
+    var found = false;
+    for (name in newTween.properties) {
+        found = false;
+        for (var i = 0; i < properties.length; i++) {
+            if (properties[i] == name) {
+                found = true;
+                break;
+            }
+        }
+
+        if (!found) {
+            newTween.properties[name] = undefined;
+            delete newTween.properties[name];
+        }
+    }
+
+    _tweenList.push(newTween);
+    return _tweenList.length - 1;
+}
+
+function _affectTweens(affectFunction, scope, properties) {
+    var affected = false;
+
+    if (!_tweenList)
+        return false;
+
+    for (var i = 0; i < _tweenList.length; i++) {
+        if (!_tweenList[i] || _tweenList[i].scope != scope)
+            continue;
+
+        if (properties.length == 0) {
+            // Can check everything
+            affectFunction(i);
+            affected = true;
+        } else {
+            // Must check whether this tween must have specific properties affected
+            var affectedProperties = new Array();
+            for (var j = 0; j < properties.length; j++) {
+                if (_tweenList[i].properties[properties[j]]) {
+                    affectedProperties.push(properties[j]);
+                }
+            }
+
+            if (affectedProperties.length > 0) {
+                var objectProperties = _getNumberOfProperties(_tweenList[i].properties);
+                if (objectProperties == affectedProperties.length) {
+                    // The list of properties is the same as all properties, so affect it all
+                    affectFunction(i);
+                    affected = true;
+                } else {
+                    // The properties are mixed, so split the tween and affect only certian specific
+                    // properties
+                    var splicedTweenIndex = _splitTweens(i, affectedProperties);
+                    affectFunction(splicedTweenIndex);
+                    affected = true;
+                }
+            }
+        }
+    }
+
+    return affected;
+};
+
+function _isInArray(string, array) {
+    var l = array.length;
+
+    for (var i = 0; i < l; i++) {
+        if (array[i] == string)
+            return true;
+    }
+
+    return false;
+}
+
+function _affectTweensWithFunction(func, args) {
+    var properties = new Array();
+    var scope = args[0];
+    var affected = false;
+    var scopes;
+
+    if (scope instanceof Array) {
+        scopes = scope.concat();
+    } else {
+        scopes = new Array(scope);
+    }
+
+    for (var i = 1; args[i] != undefined; i++) {
+        if (typeof(args[i]) == "string" && !_isInArray(args[i], properties)) {
+            if (_specialPropertySplitterList[args[i]]) {
+                // special property, get splitter array first
+                var sps = _specialPropertySplitterList[arguments[i]];
+                var specialProps = sps.splitValues(scope, null);
+                for (var j = 0; j < specialProps.length; j++)
+                    properties.push(specialProps[j].name);
+	    } else
+		properties.push(args[i]);
+	}
+    }
+
+    // the return now value means: "affect at least one tween"
+    for (var i = 0; i < scopes.length; i++) {
+        affected = affected || _affectTweens(func, scopes[i], properties);
+    }
+
+    return affected;
+}
+
+function resumeTweens() {
+    return _affectTweensWithFunction(_resumeTweenByIndex, arguments);
+};
+
+function pauseTweens() {
+    return _affectTweensWithFunction(_pauseTweenByIndex, arguments);
+};
+
+function removeTweens() {
+    return _affectTweensWithFunction(_removeTweenByIndex, arguments);
+};
+
+function _mapOverTweens(func) {
+    var rv = false;
+
+    if (_tweenList == null)
+        return false;
+
+    for (var i = 0; i < _tweenList.length; i++) {
+        if (func(i))
+            rv = true;
+    }
+
+    return rv;
+}
+
+function pauseAllTweens() {
+    return _mapOverTweens(_pauseTweenByIndex);
+};
+
+function resumeAllTweens() {
+    return _mapOverTweens(_resumeTweenByIndex);
+};
+
+function removeAllTweens() {
+    return _mapOverTweens(_removeTweenByIndex);
+};
+
+function getTweenCount(scope) {
+    if (!_tweenList)
+        return 0;
+
+    var c = 0;
+
+    for (var i = 0; i < _tweenList.length; i++) {
+        if (_tweenList[i] && _tweenList[i].scope == scope)
+            c += _getNumberOfProperties(_tweenList[i].properties);
+    }
+
+    return c;
+};
+
+function registerSpecialProperty(name, getFunction, setFunction,
+                                 parameters, preProcessFunction) {
+    _specialPropertyList[name] = {
+        getValue: getFunction,
+        setValue: setFunction,
+        parameters: parameters,
+        preProcess: preProcessFunction
+    };
+}
+
+function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {
+    _specialPropertyModifierList[name] = {
+	modifyValues: modifyFunction,
+	getValue: getFunction
+    };
+}
+
+function registerSpecialPropertySplitter(name, splitFunction, parameters) {
+    _specialPropertySplitterList[name] = {
+	splitValues: splitFunction,
+	parameters: parameters
+    };
+}
+
+//log("Done loading tweener.js");



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