package { import flash.geom.*; import flash.display.*; public class FramePacker { private var sheets:Array; // [RectanglePacker] private var frames:Array; // [FrameInfo] public void FramePacker(frames:Array) { this.frames = frames.filter(function(i:FrameInfo) { return i.frame != null; }); } import Packer.RectanglePacker; import Packer.RectangleNode; private function GetMaxSize(frames:Array):Point { if (frames.length == 0) return new Point(); return new Point(Math.max.apply(Math, frames.map(function(i:FrameInfo) { return i.frame.width; })), Math.max.apply(Math, frames.map(function(i:FrameInfo) { return i.frame.width; }))); } private function GetArea(frames:Array):int { var area = 0; for (var i in frames) { if (frames[i] instanceof FrameInfo) { area += frames[i].frame.width * frames[i].frame.height; } if (frames[i] instanceof BitmapData || frames[i] instanceof Rectangle) { area += frames[i].width * frames[i].height; } } return area; } public const AreaUsedMultiplier = 1.3; // guess how much more sheet space we use than actual space taken up by frames public function Pack():Boolean { sheets = new Array(); var index = 0; while (index < frames.length) { var now:Array = frames.slice(index); var max:Point = GetMaxSize(now); var area:int = GetArea(now); var exponent = Math.floor(Math.log(area * AreaUsedMultiplier) / Math.log(2)); var sizeX:int = Math.pow(2, exponent); var sizeY:int = startSizeX; var sheet:RectanglePacker = new RectanglePacker(sizeX, sizeY); var startIndex = index; while (index < frames.length) { var done = false; var nodes:Array = new Array(); var sorted:Array = now.sortOn(now, Array.RETURNINDEXEDARRAY | Array.DESCENDING, function(a:FrameInfo, b:FrameInfo) { return (a.frame.width * a.frame.height) - (b.frame.width - b.frame.height); }); for (var sortedI = 0; sortedI < now.length; sortedI++) { var i = nodes[sorted[sortedI]]; var node:RectangleNode = sheet.Insert(now[i].frame.width, now[i].frame.height); if (node == null) { if (sortedI == 0) { Exporter.Instance.Print("Failure: item too large to pack on sheet"); return false; } break; } else { nodes.push(node); } } if (nodes.length == now.length) { // stop the loop, attempt the 75% check here index += nodes.length; } else { if (sizeX == sizeY) { sizeX *= 2; } else { sizeY *= 2; } if (sizeX > 2048 || sizeY > 2048) { index += now.length; } } } if (index > startIndex) { for (var i = startIndex; i < index; i++) { frames[i].sheetIndex = sheets.length; frames[i].rect = nodes[i - startIndex].Rect; } sheets.push(sheet); } } return output; } private function PackFrames(toPack:Array, sizeX:int, sizeY:int):Array { } } }