Newer
Older
exporter / Utils.as
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);
		}
	}
}