package util
{
import flash.display.*;
import flash.geom.*;
public class Utils
{
public static function GetChildren(clip:MovieClip):Array
{
var ret:Array = [];
for (var i = 0; i < clip.numChildren; i++)
{
ret.push(clip.getChildAt(i));
}
return ret;
}
/*
* angle difference
* (range -Math.PI to Math.PI)
*/
public static function GetAngleDiff(a, b)
{
var angleDiff = b - a;
while (angleDiff > Math.PI)
{
angleDiff -= Math.PI * 2;
}
while (angleDiff < -Math.PI)
{
angleDiff += Math.PI * 2;
}
return angleDiff;
}
/*
* angle difference
* (range 0 to Math.PI)
*/
public static function GetAngleDiffAbs(a, b)
{
var angleDiff = GetAngleDiff(a, b);
while (angleDiff < 0)
{
angleDiff += Math.PI * 2;
}
if (angleDiff > Math.PI)
{
angleDiff = Math.PI * 2 - angleDiff;
}
return angleDiff;
}
public static function GetTransform(from:Matrix, to:Matrix)
{
var i:Matrix = from.clone();
i.invert();
var m:Matrix = to.clone();
m.concat(i);
return m;
}
public static function Decompose(m:Matrix)
{
var s:Point = ScaleFromMat(m);
m = m.clone();
var sxUnit = s.x >= 0 ? 1 : -1;
var syUnit = s.y >= 0 ? 1 : -1;
m.scale(sxUnit, syUnit);
//m.a /= sxUnit;
//m.d /= syUnit;
var rot = RotFromMat(m);
return {sx:s.x, sy:s.y, rot:rot};
}
public static function RotFromMat(m:Matrix)
{
return Math.atan2(-m.c, m.a);
}
public static function ScaleFromMat(m:Matrix):Point
{
var xAxisX = m.a;
var xAxisY = m.c;
var yAxisX = m.b;
var yAxisY = m.d;
var sx = Math.sqrt(xAxisX * xAxisX + xAxisY * xAxisY);
if (m.a < 0) sx *= -1;
var sy = Math.sqrt(yAxisX * yAxisX + yAxisY * yAxisY);
if (m.d < 0) sy *= -1;
return new Point(sx, sy);
}
public static function TransformRect(r:Rectangle, m:Matrix)
{
var p1:Point = new Point(r.left, r.top);
var p2:Point = new Point(r.right, r.top);
var p3:Point = new Point(r.left, r.bottom);
var p4:Point = new Point(r.right, r.bottom);
p1 = m.transformPoint(p1);
p2 = m.transformPoint(p2);
p3 = m.transformPoint(p3);
p4 = m.transformPoint(p4);
r.left = Math.min(p1.x, p2.x, p3.x, p4.x);
r.top = Math.min(p1.y, p2.y, p3.y, p4.y);
r.right = Math.max(p1.x, p2.x, p3.x, p4.x);
r.bottom = Math.max(p1.y, p2.y, p3.y, p4.y);
}
public static function RoundRect(r:Rectangle)
{
r.left = Math.floor(r.left);
r.top = Math.floor(r.top);
r.right = Math.ceil(r.right);
r.bottom = Math.ceil(r.bottom);
}
public static function ScaleRect(r:Rectangle, s)
{
r.left *= s;
r.top *= s;
r.right *= s;
r.bottom *= s;
}
public static function RecursivelyStop(clip)
{
if (clip is MovieClip)
{
clip.stop();
}
if (clip is DisplayObjectContainer)
{
for (var i = 0; i < clip.numChildren; i++)
{
RecursivelyStop(clip.getChildAt(i));
}
}
}
public static function WeirdGotoFrame(clip:MovieClip, frame)
{
var dir = clip.currentFrame > frame ? -1 : 1;
while (clip.currentFrame != frame)
{
RecurseDir(clip, dir);
}
}
protected static function RecurseDir(clip:MovieClip, dir)
{
for (var i = 0; i < clip.numChildren; i++)
{
var child = clip.getChildAt(i);
if (child is MovieClip)
{
RecurseDir(child, dir);
}
}
if (dir == 1)
{
clip.nextFrame();
} else {
clip.prevFrame();
}
}
protected static var tempSpace:BitmapData = null;
protected static var tempSpaceRect:Rectangle = new Rectangle();
protected static var tempSpaceMatrix:Matrix = new Matrix();
protected static var tempSpaceZero:Point = new Point();
protected static var tempSpaceColorTransform:ColorTransform = new ColorTransform(0,0,0,0,0,0,0,255);
protected static var lastDrawOffset:Point = new Point();
public static function GetAccurateBounds(clip:DisplayObject, useMatrix:Matrix = null):Rectangle
{
if (!tempSpace) tempSpace = new BitmapData(2048, 2048, true, 0x0);
var oldPad = 0;
var padAmount = 5;
var ret:Rectangle = new Rectangle();
var baseBounds:Rectangle = clip.getBounds(clip);
var boundsClip:DisplayObject = null;
if (clip is DisplayObjectContainer)
{
boundsClip = (clip as DisplayObjectContainer).getChildByName("__bounds__");
}
if (boundsClip != null)
{
baseBounds = boundsClip.getBounds(clip);
}
if (useMatrix)
{
TransformAABBRect(baseBounds, useMatrix);
}
if (boundsClip != null)
{
return baseBounds;
}
var minW = Math.pow(2, Math.ceil(Math.log(baseBounds.width + padAmount * 2) / Math.log(2)));
var minH = Math.pow(2, Math.ceil(Math.log(baseBounds.height + padAmount * 2) / Math.log(2)));
if (tempSpace == null)
{
tempSpace = new BitmapData(minW, minH, true, 0x0);
}
if (tempSpace.width < minW || tempSpace.height < minH)
{
tempSpace = new BitmapData(Math.max(tempSpace.width, minW), Math.max(tempSpace.height, minH), true, 0x0);
}
var r:Rectangle = new Rectangle();
baseBounds.left = Math.floor(baseBounds.left);
baseBounds.right = Math.ceil(baseBounds.right);
baseBounds.top = Math.floor(baseBounds.top);
baseBounds.bottom = Math.ceil(baseBounds.bottom);
var i;
var needsChecking = true;
while (needsChecking)
{
needsChecking = false;
r.left = baseBounds.left - padAmount;
r.right = baseBounds.right + padAmount;
r.top = baseBounds.top - padAmount;
r.bottom = baseBounds.bottom + padAmount;
ret = r.clone();
tempSpaceRect.x = tempSpaceRect.y = 0;
tempSpaceRect.width = tempSpace.width;
tempSpaceRect.height = tempSpace.height;
tempSpace.fillRect(tempSpaceRect, 0x0);
tempSpaceMatrix.identity();
if (useMatrix)
{
tempSpaceMatrix.a = useMatrix.a;
tempSpaceMatrix.b = useMatrix.b;
tempSpaceMatrix.c = useMatrix.c;
tempSpaceMatrix.d = useMatrix.d;
tempSpaceMatrix.tx = useMatrix.tx;
tempSpaceMatrix.ty = useMatrix.ty;
}
tempSpaceMatrix.translate(-r.left, -r.top);
lastDrawOffset.x = -r.left;
lastDrawOffset.y = -r.top;
tempSpace.draw(clip, tempSpaceMatrix);
tempSpaceRect.width = 1;
tempSpaceRect.height = r.height;
var sideMovedIn = 0;
for (i = 0; i < r.width; i++)
{
tempSpaceRect.x = i;
if (tempSpace.hitTest(tempSpaceZero, 1, tempSpaceRect))
{
break;
} else {
ret.left++;
sideMovedIn++;
}
}
if (ret.left < baseBounds.left - oldPad - 1)
{
oldPad = padAmount;
padAmount += 20;
needsChecking = true;
continue;
}
for (i = r.width - 1; i >= sideMovedIn; i--)
{
tempSpaceRect.x = i;
if (tempSpace.hitTest(tempSpaceZero, 1, tempSpaceRect))
{
break;
} else {
ret.right--;
}
}
if (ret.right > baseBounds.right + oldPad + 1 && sideMovedIn <= baseBounds.right + oldPad + 1)
{
oldPad = padAmount;
padAmount += 20;
needsChecking = true;
continue;
}
sideMovedIn = 0;
tempSpaceRect.width = r.width;
tempSpaceRect.height = 1;
tempSpaceRect.x = 0;
for (i = 0; i < r.height; i++)
{
tempSpaceRect.y = i;
if (tempSpace.hitTest(tempSpaceZero, 1, tempSpaceRect))
{
break;
} else {
ret.top++;
sideMovedIn++;
}
}
if (ret.top < baseBounds.top - oldPad - 1)
{
oldPad = padAmount;
padAmount += 20;
needsChecking = true;
continue;
}
for (i = r.height - 1; i >= sideMovedIn; i--)
{
tempSpaceRect.y = i;
if (tempSpace.hitTest(tempSpaceZero, 1, tempSpaceRect))
{
break;
} else {
ret.bottom--;
}
}
if (ret.bottom > baseBounds.bottom + oldPad + 1 && sideMovedIn <= baseBounds.bottom + oldPad + 1)
{
oldPad = padAmount;
padAmount += 20;
needsChecking = true;
continue;
}
}
return ret;
}
public static function TransformAABBRect(r:Rectangle, m:Matrix)
{
var o1X = r.left;
var o1Y = r.top;
var o2X = r.right;
var o2Y = r.top;
var o3X = r.left;
var o3Y = r.bottom;
var o4X = r.right;
var o4Y = r.bottom;
var n1X = o1X * m.a + o1Y * m.c + m.tx;
var n1Y = o1X * m.b + o1Y * m.d + m.ty;
var n2X = o2X * m.a + o2Y * m.c + m.tx;
var n2Y = o2X * m.b + o2Y * m.d + m.ty;
var n3X = o3X * m.a + o3Y * m.c + m.tx;
var n3Y = o3X * m.b + o3Y * m.d + m.ty;
var n4X = o4X * m.a + o4Y * m.c + m.tx;
var n4Y = o4X * m.b + o4Y * m.d + m.ty;
r.left = Math.min(n1X, n2X, n3X, n4X);
r.right = Math.max(n1X, n2X, n3X, n4X);
r.top = Math.min(n1Y, n2Y, n3Y, n4Y);
r.bottom = Math.max(n1Y, n2Y, n3Y, n4Y);
}
}
}