package { public class FramePacker { private var frames:Array; // [FrameInfo] public void Pack(frames:Array) { this.frames = frames.filter(function(i:FrameInfo) { return i.frame != null; }); } public function DetermineMinimumSheetSizeForClips(frames:Array):Point { /* TODO - FOR LARGE SIZED CHUNKS BETTER HANDLING FOR FINDING MINIMUM SIZE! */ var areas:Array = new Array(); for (var i = 0; i < frames.length; i++) { are } var areas:Array = frames.map(function(i:FrameInfo) { return i.frame.width * i.frame.height; }); var maxW = Math.max.apply(Math, frames.map(function(i:FrameInfo) { return i.frame.width; })); var maxH = Math.max.apply(Math, frames.map(function(i:FrameInfo) { return i.frame.height; })); var max = Math.max(maxW, maxH); var sorted:Array = areas.sort(Array.RETURNINDEXEDARRAY | Array.NUMERIC | Array.DESCENDING); var exponent = Math.ceil(Math.log(max) / Math.log(2)); max = Math.pow(2, exponent); //rough heuristic to see if this process is worth doing. //it can be slow if there are a large number of big clips. if (frames.length > 100 && max >= 512) { var s = Math.max(max, 1024); return new Point(s, s); } sheets.push(new SpriteSheet(2048, 2048)); for (var i = 0; i < frames.length; i++) { var sprite:TextureSprite = new TextureSprite(clips[sorted[i]], CACHESEQUENCES); CacheClip(clips[sorted[i]], sprite); sprites.push(sprite); } var allUsedRects:Array = new Array(); var nodesToVisit:Array = new Array(); for (var i = 0; i < sheets.length; i++) { var sheet:SpriteSheet = sheets[i]; var nodes = sheet.GetAllocator().GetLeafNodes(); for (var n = 0; n < nodes.length; n++) { allUsedRects.push(nodes[n].Rect); } } var sizeFound = false; var sheetSizeX = 64; var sheetSizeY = 64; while(!sizeFound) { var sheet:SpriteSheet = new SpriteSheet(sheetSizeX, sheetSizeY); sizeFound = true; for(var i = 0; i < allUsedRects.length; i++) { var node:RectangleNode = sheet.GetAllocator().Insert(allUsedRects[i].width, allUsedRects[i].height); if (node == null) { sizeFound = false; break; } } if (sizeFound == false) { if (sheetSizeX == sheetSizeY) { sheetSizeX *= 2; } else { sheetSizeY *= 2; } } } return new Point(sheetSizeX, sheetSizeY); } } }