/**
* Copyright (c) 2008 Donovan Adams, http://blog.hydrotik.com - donovan (at) hydrotik (dot) com
* Copyright (c) 2007 Moses Gunesch, http://www.goasap.org
*
* 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.
*/
package com.hydrotik.go {
import org.goasap.GoEngine;
import org.goasap.managers.OverlapMonitor;
import org.goasap.events.GoEvent;
import flash.filters.BevelFilter;
import flash.filters.BitmapFilter;
import flash.filters.BlurFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.DropShadowFilter;
import flash.filters.GlowFilter;
import flash.utils.Dictionary;
import org.goasap.interfaces.IManageable;
import org.goasap.interfaces.IPlayable;
import org.goasap.items.LinearGo;
import org.goasap.managers.LinearGoRepeater;
import org.goasap.utils.PlayableGroup;
import org.goasap.utils.SequenceCA;
import org.goasap.utils.SequenceStepCA;
import org.goasap.utils.customadvance.OnPlayableComplete;
import org.goasap.utils.customadvance.SequenceAdvance;
public class HydroTween extends LinearGo implements IManageable {
/*
* HydroTween
*
* @author: Donovan Adams, E-Mail: donovan[(at)]hydrotik.com, url: http://blog.hydrotik.com/
* @author: Based on Moses Gunesch Go engine, http://www.goasap.org/ - Thanks Mo!
* @version: rev31 0.4.8jg
*
* @description HydroTween is a generic tweening syntax parser for the Go tweening engine.
*
*
* @example
*
* HydroTween.go(target, {width:760}, .8, 0, Exponential.easeInOut, onCompleteHandler);
*
*
*
*
BENCHMARK PROGRESSION
*********
Go 0.4.4
Benchmark results: HydroTween - (PowerPC Quad 2.5) Feb 28, 2008 12:49 PM - PRE OPT
------------------
100 Sprites :: Start Lag: 0.02 seconds :: FPS: 96 :: End lag: 0.01
200 Sprites :: Start Lag: 0.02 seconds :: FPS: 93 :: End lag: 0.03
400 Sprites :: Start Lag: 0.05 seconds :: FPS: 90 :: End lag: 0.1
800 Sprites :: Start Lag: 0.06 seconds :: FPS: 71 :: End lag: 0.38
1600 Sprites :: Start Lag: 0.12 seconds :: FPS: 43 :: End lag: 1.76
3200 Sprites :: Start Lag: 0.25 seconds :: FPS: 18 :: End lag: 7.95
Test flatlined! (0-FPS seconds:15)
6400 Sprites :: Start Lag: 0.54 seconds :: FPS: 1 :: End lag: 15.07
Benchmark results: Go - HydroBenchmark - NEW VERSION - MacPro 2 x 3.0GHz dual Core May 6, 2008 12:54
------------------
100 Sprites :: Start Lag: 0.01 seconds :: FPS: 97 :: End lag: 0.02
200 Sprites :: Start Lag: 0.01 seconds :: FPS: 97 :: End lag: 0.01
400 Sprites :: Start Lag: 0.02 seconds :: FPS: 97 :: End lag: 0.04
800 Sprites :: Start Lag: 0.04 seconds :: FPS: 95 :: End lag: 0.16
1600 Sprites :: Start Lag: 0.08 seconds :: FPS: 84 :: End lag: 0.62
3200 Sprites :: Start Lag: 0.14 seconds :: FPS: 61 :: End lag: 2.46
***********************************************************************************************/
public static const VERSION:String = "HydroTween 0.4.8 rev31 / Go 0.4.8jg1";
public static const INFO:String = VERSION + " (c) Donovan Adams/Moses Gunesch, MIT Licensed.";
public static var VERBOSE : Boolean = true;
private static var _init : Boolean = false;
// DEFAULTS
protected var _target : Object;
protected var _closure : Function;
protected var _update : Function;
protected var _tweenStartProps : Dictionary = new Dictionary(true);
protected var _htweens : Dictionary = new Dictionary(true);
protected static var _propertyList:Dictionary = new Dictionary(false);
protected var _tweenList:Dictionary = new Dictionary(true);
private static var _r_lum:Number = 0.212671;
private static var _g_lum:Number = 0.715160;
private static var _b_lum:Number = 0.072169;
private static const DELTA_INDEX:Array = [
0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11,
0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25,
2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8,
4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0,
7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8,
10.0
];
private static const IDENTITY:Array = [
1,0,0,0,0,
0,1,0,0,0,
0,0,1,0,0,
0,0,0,1,0,
0,0,0,0,1];
protected var _matrix : Array = [];
protected var _changeMatrix : Array = [];
protected var _startMatrix : Array = [];
public static const RESET:int = -1;
// Papervision
private static var _viewport:*;
private static var _camera:*;
private static var _scene:*;
private static var _renderer : *;
private static var _init3D : Boolean;
private static function init():void{
if (_init) { return; }
_init = true;
if (!GoEngine.getManager("OverlapMonitor")) GoEngine.addManager(new OverlapMonitor());
_propertyList["x"] = {prop:"x", read:genericRead, write:genericWrite};
_propertyList["y"] = {prop:"y", read:genericRead, write:genericWrite};
_propertyList["scaleX"] = {prop:"scaleX", read:genericRead, write:genericWrite};
_propertyList["scaleY"] = {prop:"scaleY", read:genericRead, write:genericWrite};
_propertyList["width"] = {prop:"width", read:genericRead, write:genericWrite};
_propertyList["height"] = {prop:"height", read:genericRead, write:genericWrite};
_propertyList["rotation"] = {prop:"rotation", read:genericRead, write:genericWrite};
_propertyList["alpha"] = {prop:"alpha", read:genericRead, write:genericWrite};
// BevelFilter ----------------------------------------------------------------------------
_propertyList["Bevel_angle"] = {prop:"angle", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_blurX"] = {prop:"blurX", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_blurY"] = {prop:"blurY", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_color"] = {prop:"color", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_distance"] = {prop:"distance", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_highlightAlpha"] = {prop:"highlightAlpha", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_highlightColor"] = {prop:"highlightColor", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_quality"] = {prop:"quality", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_shadowAlpha"] = {prop:"shadowAlpha", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_shadowColor"] = {prop:"shadowColor", definition: BevelFilter, read:filterRead, write:filterWrite};
_propertyList["Bevel_strength"] = {prop:"strength", definition: BevelFilter, read:filterRead, write:filterWrite};
// BlurFilter ----------------------------------------------------------------------------
_propertyList["Blur_blurX"] = {prop:"blurX", definition: BlurFilter, read:filterRead, write:filterWrite};
_propertyList["Blur_blurY"] = {prop:"blurY", definition: BlurFilter, read:filterRead, write:filterWrite};
_propertyList["Blur_quality"] = {prop:"quality", definition: BlurFilter, read:filterRead, write:filterWrite};
// DropShadowFilter ----------------------------------------------------------------------------
_propertyList["DropShadow_alpha"] = {prop:"alpha", definition: DropShadowFilter, read:filterRead, write:filterWrite};
_propertyList["DropShadow_angle"] = {prop:"angle", definition: DropShadowFilter, read:filterRead, write:filterWrite};
_propertyList["DropShadow_blurX"] = {prop:"blurX", definition: DropShadowFilter, read:filterRead, write:filterWrite};
_propertyList["DropShadow_blurY"] = {prop:"blurY", definition: DropShadowFilter, read:filterRead, write:filterWrite};
_propertyList["DropShadow_color"] = {prop:"color", definition: DropShadowFilter, read:filterRead, write:filterWrite};
_propertyList["DropShadow_distance"] = {prop:"distance", definition: DropShadowFilter, read:filterRead, write:filterWrite};
_propertyList["DropShadow_quality"] = {prop:"quality", definition: DropShadowFilter, read:filterRead, write:filterWrite};
_propertyList["DropShadow_strength"] = {prop:"strength", definition: DropShadowFilter, read:filterRead, write:filterWrite};
// GlowFilter ----------------------------------------------------------------------------
_propertyList["Glow_alpha"] = {prop:"alpha", definition: GlowFilter, read:filterRead, write:filterWrite};
_propertyList["Glow_blurX"] = {prop:"blurX", definition: GlowFilter, read:filterRead, write:filterWrite};
_propertyList["Glow_blurY"] = {prop:"blurY", definition: GlowFilter, read:filterRead, write:filterWrite};
_propertyList["Glow_color"] = {prop:"color", definition: GlowFilter, read:filterRead, write:filterWrite};
_propertyList["Glow_quality"] = {prop:"quality", definition: GlowFilter, read:filterRead, write:filterWrite};
_propertyList["Glow_strength"] = {prop:"strength", definition: GlowFilter, read:filterRead, write:filterWrite};
// Image ----------------------------------------------------------------------------
_propertyList["matrix"] = {prop:"matrix", definition: ColorMatrixFilter, read:filterRead, write:filterWrite, adjust:adjustMatrix};
_propertyList["brightness"] = {prop:"matrix", definition: ColorMatrixFilter, read:filterRead, write:filterWrite, adjust:adjustBrightness};
_propertyList["contrast"] = {prop:"matrix", definition: ColorMatrixFilter, read:filterRead, write:filterWrite, adjust:adjustContrast};
_propertyList["saturation"] = {prop:"matrix", definition: ColorMatrixFilter, read:filterRead, write:filterWrite, adjust:adjustSaturation};
_propertyList["hue"] = {prop:"matrix", definition: ColorMatrixFilter, read:filterRead, write:filterWrite, adjust:adjustHue};
_propertyList["tint"] = {prop:"matrix", definition: ColorMatrixFilter, read:filterRead, write:filterWrite, adjust:adjustColor};
// Hex ----------------------------------------------------------------------------
_propertyList["color"] = {prop:"matrix", definition: ColorMatrixFilter, read:filterRead, write:filterWrite, adjust:adjustHex};
// Sound ----------------------------------------------------------------------------
_propertyList["volume"] = {prop:"volume", read:transformRead, write:transformWrite, path:"soundTransform"};
_propertyList["pan"] = {prop:"pan", read:transformRead, write:transformWrite, path:"soundTransform"};
//Text
_propertyList["text"] = {prop:"text", read:textRead, write:textWrite, path:"text"};
//Papervision
_propertyList["z"] = {prop:"z", read:genericRead, write:genericWrite};
_propertyList["rotationX"] = {prop:"rotationX", read:genericRead, write:genericWrite};
_propertyList["rotationY"] = {prop:"rotationY", read:genericRead, write:genericWrite};
_propertyList["rotationZ"] = {prop:"rotationZ", read:genericRead, write:genericWrite};
_propertyList["scale"] = {prop:"scale", read:genericRead, write:genericWrite};
_propertyList["scaleX"] = {prop:"scaleX", read:genericRead, write:genericWrite};
_propertyList["scaleY"] = {prop:"scaleY", read:genericRead, write:genericWrite};
_propertyList["scaleZ"] = {prop:"scaleZ", read:genericRead, write:genericWrite};
_propertyList["sceneX"] = {prop:"sceneX", read:genericRead, write:genericWrite};
_propertyList["sceneY"] = {prop:"sceneY", read:genericRead, write:genericWrite};
_propertyList["sceneZ"] = {prop:"sceneZ", read:genericRead, write:genericWrite};
}
public static function init3D(renderer:*, scene:*, camera:*, viewport:*):void{
_renderer = renderer;
_scene = scene;
_camera = camera;
_viewport = viewport;
_init3D = true;
}
public static function go(target : Object,
propsTo : Object = null,
duration : Number = NaN,
delay : Number = NaN,
easing : Function = null,
closure : Function = null,
update : Function = null,
extraEasingParams : Array = null,
repeater : Object=null,
useRelative : Boolean = false,
useRounding : Boolean = false,
pulseInterval : Number = 31
) : IPlayable {
if (target==null) { return null; }
var isGroup:Boolean = target is Array;
var go:IPlayable = (isGroup ? new PlayableGroup() : null);
var targArray:Array = (isGroup ? target as Array : [target]);
for each (var targ:Object in targArray) {
var tween: HydroTween = new HydroTween(
targ,
propsTo,
duration,
delay,
easing,
closure,
update,
extraEasingParams,
repeater,
useRelative,
useRounding,
pulseInterval
);
if (isGroup)
(go as PlayableGroup).addChild(tween);
else
go = tween;
}
go.start();
return go;
}
public static function parseSequence(...actions): SequenceCA {
var seq:SequenceCA = new SequenceCA();
for (var i:int = 0; i -1) return true;
}
}
return false;
}
// When there's a conflict the manager calls this method so you can stop the tween.
public function releaseHandling(...params) : void {
//trace(this + " releaseHandling()");
super.stop();
}
/* ****************************************************************************************
PROPERTY UPDATERS
******************************************************************************************/
//Generic ---------------------------------------------------------------------------------
protected static function genericRead(targ:Object, key:String):Number {
return targ[_propertyList[key].prop];
}
protected static function genericWrite(targ:Object, key:String, val:Number, val2:Number = 0):void {
targ[_propertyList[key].prop] = val;
}
//Filter ---------------------------------------------------------------------------------
protected static function filterRead(targ:Object, key:String):* {
var defVals:BitmapFilter;
var filters:Array = targ.filters;
for (var i:int = 0; i < targ.filters.length; i++) {
if (filters[i] is _propertyList[key].definition) {
if(_propertyList[key].prop != "color" && _propertyList[key].prop != "highlightColor" && _propertyList[key].prop != "shadowColor")
return (targ.filters[i][_propertyList[key].prop]);
}
}
defVals = getFilterDefaults()[_propertyList[key].definition];
return defVals[_propertyList[key].prop];
}
protected static function filterWrite(targ:Object, key:String, val:*, val2:* = 0): void {
var filters:Array = targ.filters;
var filter:BitmapFilter;
for (var i:int = 0; i < filters.length; i++) {
if (filters[i] is _propertyList[key].definition) {
filters[i][_propertyList[key].prop] = (_propertyList[key].prop != "color" && _propertyList[key].prop != "highlightColor" && _propertyList[key].prop != "shadowColor") ? val : val2;
targ.filters = filters;
return;
}
}
if (filters == null) filters = new Array();
filter = getFilterDefaults()[_propertyList[key].definition];
filter[_propertyList[key].prop] = val;
filters.push(filter);
targ.filters = filters;
}
//Matrix/Color ---------------------------------------------------------------------------------
private function matrixWrite(element:*, index:int, arr:Array):Number {
return (_startMatrix[index] + _changeMatrix[index] * _position);
}
private function matrixSubtraction(element:*, index:int, arr:Array):Number {
return element - _startMatrix[index];
}
// Borrowed and tweaked w/permission from Grant Skinner's
// ColorMatrix AS3 Class - thanks Grant!
// http://www.gskinner.com/blog/archives/2007/12/colormatrix_upd.html
public static function adjustMatrix(array:Array, val:Array):Array {
return multiplyMatrix(array, val);
}
public static function adjustColor(array:Array, rgb:Number, amount:Number = 1):Array {
if (rgb == -1) return multiplyMatrix(IDENTITY, array);
var r:Number = ((rgb >> 16) & 0xff) / 255;
var g:Number = ((rgb >> 8) & 0xff) / 255;
var b:Number = (rgb & 0xff) / 255;
var inv:Number = 1 - amount;
return multiplyMatrix([inv + amount * r * _r_lum, amount * r * _g_lum, amount * r * _b_lum, 0, 0,
amount * g * _r_lum, inv + amount * g * _g_lum, amount * g * _b_lum, 0, 0,
amount * b * _r_lum, amount * b * _g_lum, inv + amount * b * _b_lum, 0, 0,
0, 0, 0, 1, 0], array);
}
public static function adjustHex(array:Array, rgb:Number, amount:Number = 1):Array {
if (rgb == -1) return multiplyMatrix(IDENTITY, array);
var r:Number = ((rgb >> 16) & 0xff) / 255;
var g:Number = ((rgb >> 8) & 0xff) / 255;
var b:Number = (rgb & 0xff) / 255;
var inv:Number = 1 - amount;
return multiplyMatrix([inv + amount * r, amount * r, amount * r, 0, 0,
amount * g, inv + amount * g, amount * g, 0, 0,
amount * b, amount * b, inv + amount * b, 0, 0,
0, 0, 0, 1, 0], array);
}
public static function adjustBrightness(array:Array, val:Number):Array {
val = cleanValue(val,10) * 100;
if (val == 0 || isNaN(val)) { return array; }
return multiplyMatrix(array, [
1,0,0,0,val,
0,1,0,0,val,
0,0,1,0,val,
0,0,0,1,0,
0,0,0,0,1
]);
}
public static function adjustContrast(array:Array, val:Number):Array {
val = cleanValue(val,1) * 100;
if (val == 0 || isNaN(val)) { return array; }
var x:Number;
if (val<0) {
x = 127+val/100*127;
} else {
x = val%1;
if (x == 0) {
x = DELTA_INDEX[val];
} else {
x = DELTA_INDEX[(val<<0)]*(1-x)+DELTA_INDEX[(val<<0)+1]*x;
}
x = x*127+127;
}
return multiplyMatrix(array, [
x/127,0,0,0,0.5*(127-x),
0,x/127,0,0,0.5*(127-x),
0,0,x/127,0,0.5*(127-x),
0,0,0,1,0,
0,0,0,0,1
]);
}
public static function adjustSaturation(array:Array, val:Number):Array {
val = cleanValue(val,10) * 100;
if (val == 0 || isNaN(val)) { return array; }
var x:Number = 1+((val > 0) ? 3*val/100 : val/100);
var _r_lum:Number = 0.3086;
var _g_lum:Number = 0.6094;
var _b_lum:Number = 0.0820;
return multiplyMatrix(array, [
_r_lum*(1-x)+x,_g_lum*(1-x),_b_lum*(1-x),0,0,
_r_lum*(1-x),_g_lum*(1-x)+x,_b_lum*(1-x),0,0,
_r_lum*(1-x),_g_lum*(1-x),_b_lum*(1-x)+x,0,0,
0,0,0,1,0,
0,0,0,0,1
]);
}
public static function adjustHue(array:Array, val:Number):Array {
val = cleanValue(val,180)/180*Math.PI;
if (val == 0 || isNaN(val)) { return array; }
var cosVal:Number = Math.cos(val);
var sinVal:Number = Math.sin(val);
return multiplyMatrix(array, [
_r_lum+cosVal*(1-_r_lum)+sinVal*(-_r_lum),_g_lum+cosVal*(-_g_lum)+sinVal*(-_g_lum),_b_lum+cosVal*(-_b_lum)+sinVal*(1-_b_lum),0,0,
_r_lum+cosVal*(-_r_lum)+sinVal*(0.143),_g_lum+cosVal*(1-_g_lum)+sinVal*(0.140),_b_lum+cosVal*(-_b_lum)+sinVal*(-0.283),0,0,
_r_lum+cosVal*(-_r_lum)+sinVal*(-(1-_r_lum)),_g_lum+cosVal*(-_g_lum)+sinVal*(_g_lum),_b_lum+cosVal*(1-_b_lum)+sinVal*(_b_lum),0,0,
0,0,0,1,0,
0,0,0,0,1
]);
}
// multiplies one matrix against another:
protected static function multiplyMatrix(array:Array, matrix:Array):Array {
var col:Array = [];
var output:Array = [];
for (var i:int=0;i<5;i++) {
for (var j:int=0;j<5;j++) {
col[j] = array[j+i*5];
}
for (j=0;j<5;j++) {
var val:Number=0;
for (var k:Number=0;k<5;k++) {
val += matrix[j+k*5]*col[k];
}
output[j+i*5] = val;
}
}
return output;
}
// make sure values are within the specified range, hue has a limit of 180, others are 100:
protected static function cleanValue(val:Number,range:Number):Number {
return Math.min(range,Math.max(-range,val));
}
// makes sure matrixes are 5x5 (25 long):
protected static function fixMatrix(matrix:Array = null):Array {
if (matrix == null) { return IDENTITY; }
if (matrix is Array) { matrix = matrix.slice(0); }
if (matrix.length < IDENTITY.length) {
matrix = matrix.slice(0,matrix.length).concat(IDENTITY.slice(matrix.length,IDENTITY.length));
} else if (matrix.length > IDENTITY.length) {
matrix = matrix.slice(0,IDENTITY.length);
}
return matrix;
}
protected static function transformRead(targ:Object, key:String):Number {
return targ[_propertyList[key].path][_propertyList[key].prop];
}
protected static function transformWrite(targ:Object, key:String, val:Number, val2:Number = 0): void {
var tf:* = targ[_propertyList[key].path];
tf[_propertyList[key].prop] = val;
targ[_propertyList[key].path] = tf;
}
protected static function textRead(targ:Object, key:String):Number {
return new Number(targ[_propertyList[key].path]);
}
protected static function textWrite(targ:Object, key:String, val:Number, val2:Number = 0): void {
targ[_propertyList[key].path] = int(val).toString();
}
}
}
class HydroError extends Error
{
public function HydroError(message:String)
{
super(message);
}
}