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