/**
* VERSION: 1.02
* DATE: 2010-10-11
* ACTIONSCRIPT VERSION: 2
* UPDATES AND DOCUMENTATION AT: http://www.GreenSock.com
**/
import com.greensock.*;
import com.greensock.plugins.*;
import flash.display.*;
import flash.geom.*;
/**
* TransformMatrixPlugin allows you to tween a MovieClip's transform.matrix values directly
* (a, b, c, d, tx, and ty
) or use common properties like _x, _y, _xscale, _yscale,
* skewX, skewY, _rotation
and even shortRotation
.
* To skew without adjusting scale visually, use skewX2 and skewY2 instead of skewX and skewY.
*
*
* USAGE:
*
* import com.greensock.TweenLite;
* import com.greensock.plugins.~~;
* TweenPlugin.activate([TransformMatrixPlugin]); //activation is permanent in the SWF, so this line only needs to be run once.
*
* TweenLite.to(mc, 1, {transformMatrix:{_x:50, _y:300, _xscale:200, _yscale:200}});
*
* //-OR-
*
* TweenLite.to(mc, 1, {transformMatrix:{tx:50, ty:300, a:2, d:2}});
*
*
*
* Copyright 2011, GreenSock. All rights reserved. This work is subject to the terms in http://www.greensock.com/terms_of_use.html or for corporate Club GreenSock members, the software agreement that was issued with the corporate membership.
*
* @author Jack Doyle, jack@greensock.com
*/
class com.greensock.plugins.TransformMatrixPlugin extends TweenPlugin {
/** @private **/
public static var API:Number = 1.0; //If the API/Framework for plugins changes in the future, this number helps determine compatibility
/** @private **/
private static var _DEG2RAD:Number = Math.PI / 180;
/** @private **/
private var _transform:Transform;
/** @private **/
private var _matrix:Matrix;
/** @private **/
private var _txStart:Number;
/** @private **/
private var _txChange:Number;
/** @private **/
private var _tyStart:Number;
/** @private **/
private var _tyChange:Number;
/** @private **/
private var _aStart:Number;
/** @private **/
private var _aChange:Number;
/** @private **/
private var _bStart:Number;
/** @private **/
private var _bChange:Number;
/** @private **/
private var _cStart:Number;
/** @private **/
private var _cChange:Number;
/** @private **/
private var _dStart:Number;
/** @private **/
private var _dChange:Number;
/** @private **/
private var _angleChange:Number;
/** @private **/
public function TransformMatrixPlugin() {
super();
this.propName = "transformMatrix";
this.overwriteProps = ["_x","_y","_xscale","_yscale","_rotation","shortRotation","transformMatrix","transformAroundPoint","transformAroundCenter"];
}
/** @private **/
public function onInitTween(target:Object, value:Object, tween:TweenLite):Boolean {
_transform = target.transform;
_matrix = _transform.matrix;
var matrix:Matrix = _matrix.clone();
_txStart = matrix.tx;
_tyStart = matrix.ty;
_aStart = matrix.a;
_bStart = matrix.b;
_cStart = matrix.c;
_dStart = matrix.d;
if (value._x != undefined) {
_txChange = (typeof(value._x) == "number") ? value._x - _txStart : Number(value._x);
} else if (value.tx != undefined) {
_txChange = value.tx - _txStart;
} else {
_txChange = 0;
}
if (value._y != undefined) {
_tyChange = (typeof(value._y) == "number") ? value._y - _tyStart : Number(value._y);
} else if (value.ty != undefined) {
_tyChange = value.ty - _tyStart;
} else {
_tyChange = 0;
}
_aChange = (value.a != undefined) ? value.a - _aStart : 0;
_bChange = (value.b != undefined) ? value.b - _bStart : 0;
_cChange = (value.c != undefined) ? value.c - _cStart : 0;
_dChange = (value.d != undefined) ? value.d - _dStart : 0;
_angleChange = 0;
if ((value._rotation != undefined) || (value.shortRotation != undefined) || (value.scale != undefined && !(value instanceof Matrix)) || (value._xscale != undefined) || (value._yscale != undefined) || (value.skewX != undefined) || (value.skewY != undefined) || (value.skewX2 != undefined) || (value.skewY2 != undefined)) {
var ratioX:Number, ratioY:Number;
var scaleX:Number = Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b); //Bugs in the Flex framework prevent DisplayObject.scaleX from working consistently, so we must determine it using the matrix.
if (matrix.a < 0 && matrix.d > 0) {
scaleX = -scaleX;
}
var scaleY:Number = Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d); //Bugs in the Flex framework prevent DisplayObject.scaleY from working consistently, so we must determine it using the matrix.
if (matrix.d < 0 && matrix.a > 0) {
scaleY = -scaleY;
}
var angle:Number = Math.atan2(matrix.b, matrix.a); //Bugs in the Flex framework prevent DisplayObject.rotation from working consistently, so we must determine it using the matrix
if (matrix.a < 0 && matrix.d >= 0) {
angle += (angle <= 0) ? Math.PI : -Math.PI;
}
var skewX:Number = Math.atan2(-_matrix.c, _matrix.d) - angle;
var finalAngle:Number = angle;
if (value.shortRotation != undefined) {
var dif:Number = ((value.shortRotation * _DEG2RAD) - angle) % (Math.PI * 2);
if (dif > Math.PI) {
dif -= Math.PI * 2;
} else if (dif < -Math.PI) {
dif += Math.PI * 2;
}
finalAngle += dif;
} else if (value._rotation != undefined) {
finalAngle = (typeof(value._rotation) == "number") ? value._rotation * _DEG2RAD : Number(value._rotation) * _DEG2RAD + angle;
}
var finalSkewX:Number = (value.skewX != undefined) ? (typeof(value.skewX) == "number") ? Number(value.skewX) * _DEG2RAD : Number(value.skewX) * _DEG2RAD + skewX : 0;
if (value.skewY != undefined) { //skewY is just a combonation of rotation and skewX
var skewY:Number = (typeof(value.skewY) == "number") ? value.skewY * _DEG2RAD : Number(value.skewY) * _DEG2RAD - skewX;
finalAngle += skewY + skewX;
finalSkewX -= skewY;
}
if (finalAngle != angle) {
if ((value._rotation != undefined) || (value.shortRotation != undefined)) {
_angleChange = finalAngle - angle;
finalAngle = angle; //to correctly affect the skewX calculations below
} else {
matrix.rotate(finalAngle - angle);
}
}
if (value.scale != undefined) {
ratioX = Number(value.scale) * 0.01 / scaleX;
ratioY = Number(value.scale) * 0.01 / scaleY;
if (typeof(value.scale) != "number") { //relative value
ratioX += 1;
ratioY += 1;
}
} else {
if (value._xscale != undefined) {
ratioX = Number(value._xscale) * 0.01 / scaleX;
if (typeof(value._xscale) != "number") { //relative value
ratioX += 1;
}
}
if (value._yscale != undefined) {
ratioY = Number(value._yscale) * 0.01 / scaleY;
if (typeof(value._yscale) != "number") { //relative value
ratioY += 1;
}
}
}
if (finalSkewX != skewX) {
matrix.c = -scaleY * Math.sin(finalSkewX + finalAngle);
matrix.d = scaleY * Math.cos(finalSkewX + finalAngle);
}
if (value.skewX2 != undefined) {
if (typeof(value.skewX2) == "number") {
matrix.c = Math.tan(0 - (value.skewX2 * _DEG2RAD));
} else {
matrix.c += Math.tan(0 - (Number(value.skewX2) * _DEG2RAD));
}
}
if (value.skewY2 != undefined) {
if (typeof(value.skewY2) == "number") {
matrix.b = Math.tan(value.skewY2 * _DEG2RAD);
} else {
matrix.b += Math.tan(Number(value.skewY2) * _DEG2RAD);
}
}
if (ratioX || ratioX == 0) { //faster than isNaN()
matrix.a *= ratioX;
matrix.b *= ratioX;
}
if (ratioY || ratioY == 0) {
matrix.c *= ratioY;
matrix.d *= ratioY;
}
_aChange = matrix.a - _aStart;
_bChange = matrix.b - _bStart;
_cChange = matrix.c - _cStart;
_dChange = matrix.d - _dStart;
}
return true;
}
/** @private **/
public function set changeFactor(n:Number):Void {
_matrix.a = _aStart + (n * _aChange);
_matrix.b = _bStart + (n * _bChange);
_matrix.c = _cStart + (n * _cChange);
_matrix.d = _dStart + (n * _dChange);
if (_angleChange) {
//about 3-4 times faster than _matrix.rotate(_angleChange * n);
var cos:Number = Math.cos(_angleChange * n);
var sin:Number = Math.sin(_angleChange * n);
var a:Number = _matrix.a;
var c:Number = _matrix.c;
_matrix.a = a * cos - _matrix.b * sin;
_matrix.b = a * sin + _matrix.b * cos;
_matrix.c = c * cos - _matrix.d * sin;
_matrix.d = c * sin + _matrix.d * cos;
}
_matrix.tx = _txStart + (n * _txChange);
_matrix.ty = _tyStart + (n * _tyChange);
_transform.matrix = _matrix;
}
}