package
{
import flash.display.*;
import flash.geom.*;
public class Utils
{
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);
}
}
}