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); } } }