#! /bin/bash
+VERBOSE=""
+SRC="src/Y src/ezl src/tanks"
+EXCLUDE="--exclude=$(join ' --exclude=' 'tmp' 'src' 'bin' $*)"
+GIT_VERSION=$(git show --oneline . | head -n1 | cut -d ' ' -f 1)
+
+
function halp () {
cat >&2 <<-HALP
The Littlest Deployer of Battletanks
Options:
-h Displays this help
- -v Verbose logging
+ -v Verbose
-n Dry-run
-C Clean before rebuilding
- -G Only emit the deploy version (Git commit abbreviation)
+ -G Only emit the deploy version (Git commit abbreviation: $GIT_VERSION)
HALP
}
SHIFT=0
function incshift () { SHIFT=$(( $SHIFT + ${1:-1} )); }
function fail () { echo; echo "PREDICTABLE FAILURE. $1" >&2; exit 1; }
-function join () { sep="$1"; out="$2"; shift 2; for a in $*; do out="${out}${sep}${a}"; done; echo "$out"; }
+function join () { sep="$1"; printf "$2"; shift 2; for a in $*; do printf "$sep$a"; done; echo; }
+function log () { test "$VERBOSE" && echo && echo "$*"; }
for opt in $*; do
echo $opt | egrep -xq -e '--?h(e(lp?)?)?' && { halp; exit 0; }
done
-while getopts "nvCG" opt; do
+while getopts ":vnCG" opt; do
case $opt in
- n ) DRY_RUN="--dry-run"; incshift ;;
v ) VERBOSE="-v"; incshift ;;
+ n ) DRY_RUN="--dry-run"; incshift ;;
C ) CLEAN="--clean"; incshift ;;
G ) GIT_VERSION_ONLY=1; incshift ;;
+ * ) fail "Unknown option: $OPTARG" ;;
esac
done
shift $SHIFT
-SRC="src/Y src/ezl src/tanks"
-EXCLUDE="--exclude=$(join ' --exclude=' 'tmp' 'src' 'bin' $*)"
-GIT_VERSION=$(git show --oneline . | head -n1 | cut -d ' ' -f 1)
-
if test "$GIT_VERSION_ONLY"; then
echo "$GIT_VERSION"
exit
--- /dev/null
+var Y = require('Y').Y
+, evt = require('evt')
+,
+
+/**
+ * All easing functions adhere to the following interface.
+ *
+ * @param {Float} p Proportion completed [0-1].
+ * @param {Number} elapsed Miliseconds elapsed since start.
+ * @param {Number} start Starting value.
+ * @param {Number} span Delta value (finish - start) to animate.
+ * @param {Number} duration Total duration in miliseconds of the animation.
+ */
+Easing =
+exports['Easing'] = {
+ 'linear' : function linearEasing( p, elapsed, start, span, duration ) {
+ return start + span * p;
+ },
+
+ 'swing' : function swingEasing( p, elapsed, start, span, duration ) {
+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * span + start;
+ }
+}
+,
+
+
+lookupEasing =
+exports['lookupEasing'] =
+function lookupEasing(name, prop){
+ if ( Y.isFunction(name) )
+ return name;
+ if (name in Easing)
+ return Easing[name];
+ if ( !(Y.isPlainObject(name) && prop in name) )
+ throw new Error('Unknown easing function '+name+'!');
+ return lookupEasing(name[prop]);
+}
+,
+
+
+Fx =
+exports['Fx'] =
+Y.subclass('Fx', function setupFx(Fx){
+ var VAL_PATTERN = /^([+\-]=)?([\d+.\-]+)(.*)$/;
+
+ this['init'] =
+ function initFx(obj, duration, prop, val, easing){
+ var parts = VAL_PATTERN.exec(val)
+ , rel = parts[1]
+ , val = parseFloat(parts[2])
+ , unit = parts[3] || null
+ ;
+
+ this.obj = obj;
+ this.duration = duration;
+ this.prop = prop;
+ this.unit = unit;
+ this.easing = Easing[easing];
+
+ this.start = this.cur = Y.attr(obj, prop);
+ if (rel) {
+ this.span = val*(rel === '-=' ? -1 : 1);
+ this.finish = this.start + this.span;
+ } else {
+ this.span = val - this.start;
+ this.finish = val;
+ }
+ };
+
+ this['start'] =
+ function start(now){
+ if (this.running) return;
+ this.startTime = now || new Date().getTime();
+ this.running = true;
+ };
+
+ this['stop'] =
+ function stop(){
+ this.running = false;
+ };
+
+ this['tick'] =
+ function tick(elapsed, now){
+ if (!this.running)
+ return false;
+
+ var p = (now - this.startTime) / this.duration
+ , v = this.cur = this.start + this.easing(p, 0, this.span, this.duration) ;
+ Y.attr(this.obj, this.prop, ( this.unit !== null ? v+this.unit : v ));
+
+ return true;
+ };
+})
+,
+
+Animation =
+exports['Animation'] =
+new evt.Class('Animation', function setupAnimation(Animation){
+ Y.extend(this, {
+ 'started': 0,
+ 'running': false
+ });
+
+ var defOptions = {
+ 'delay' : 0,
+ // 'queue' : undefined,
+ 'easing' : 'linear'
+ // 'complete' : null,
+ // 'step' : null
+ };
+
+ /**
+ * @param {Object} obj Object to animate.
+ * @param {Number} duration Duration (ms) of animation.
+ * @param {Object} props Object whose keys are the property-names to animate
+ * paired with the target value. Animated properties can also be relative.
+ * If a value is supplied with a leading += or -= sequence of characters,
+ * then the target value is computed by adding or subtracting the given
+ * number from the current value of the property.
+ * @param {Object} [options] Animation options:
+ * * {Number} [delay=0] Milliseconds to wait before beginning animation.
+ * * {Boolean} [queue=true] Indicates whether to place the animation
+ * in the effects queue to run when other animations have finished.
+ * If false, the animation will begin after `delay` milliseconds;
+ * likewise, if `delay` is non-zero `queue` defaults to `false`
+ * instead.
+ * * {String|Function|Object} [easing='linear'] Name of easing function
+ * used to calculate each step value, or a function, or a map of
+ * properties to either of the above.
+ */
+ this['init'] =
+ function initAnimation(obj, duration, props, options){
+ this.obj = obj;
+ this.duration = duration;
+ this.props = props;
+
+ this.options = options = Y.extend({}, defOptions, options);
+ if ( !('queue' in options) )
+ options.queue = !options.delay;
+
+ this.fx = Y(this.props)
+ .reduce(function(fx, val, prop){
+ var easing = lookupEasing(options.easing, prop);
+ return fx.push(new Fx(obj, duration, prop, val, easing));
+ }, Y([]) );
+
+ // TODO: Handle Queuing -- should happen in target objects who provide the API
+ };
+
+ this['start'] =
+ function start(now){
+ if (this.running) return;
+ this.started = now || new Date().getTime();
+ this.running = true;
+ this.waiting = !!this.options.delay;
+ };
+
+ this['tick'] =
+ function tick(elapsed, now){
+ if (this.waiting && (now < this.started+this.options.delay))
+ return true;
+
+
+ this.waiting = false;
+ return true;
+ };
+
+});