In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Texture packer

Found this on my hard drive, I don't think I ever actually used it...

ref: http://www.blackpawn.com/texts/lightmaps/default.html
Get Adobe Flash player
by yonatan 22 May 2013
  • Forked from FLASHMAFIA's Lil' Boxes...
  • Diff: 177
  • Related works: 6
  • Talk

    hemingway at 22 May 2013 09:15
    why 'Node' as naming convention? do you continue to use this convention when naming similar algorithms?
    yonatan at 22 May 2013 10:00
    They're called nodes in blackpawn's pseudocode so I just went along with that. I guess it's because he thinks of texture space as a graph in this case.
    FLASHMAFIA at 22 May 2013 11:56
    yup, node = [ own properties + link(s) to other node(s) ] ~like a tree in real life : nodes would be the point of intersection of the branches ( and the branches would be the links )
    FLASHMAFIA at 22 May 2013 12:19
    Yonathan : thanks, btw! ; > Now i was more looking into something like : http://packery.metafizzy.co/ See the different packing styles + you can drag things ect... But this packing sexiness is only for javascript. I'll fork this mother forker up to AS3 in good time.
    FLASHMAFIA at 22 May 2013 15:23
    Having evaluated different options, i think you have to cheat on box sizes to have a packing that actually looks good. ( I think that's what js-packery does -- have to check that -- )
    lizhi at 23 May 2013 13:51
    how to add padding?gap
    yonatan at 23 May 2013 19:57
    change "color" to "0" in line 27?

    Tags

    Embed
/**
 * Copyright yonatan ( http://wonderfl.net/user/yonatan )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/e7P0
 */

// forked from FLASHMAFIA's Lil' Boxes...
package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import org.si.b3.*;

    [SWF(width = '465', height = '465', frameRate = '1')]
    public class main extends Sprite
    {
        private const NUM_BOXES : uint = 250;

        private var boxes:Vector.<CMLMovieClipTexture> = new Vector.<CMLMovieClipTexture>(NUM_BOXES, true);
        private var bmp:Bitmap = new Bitmap;

        function main() {
            addChild(bmp);
            addEventListener(Event.ENTER_FRAME, oef);
        }

        private function oef(e:Event):void
        {
            for(var i:int=0; i<NUM_BOXES; i++) {
                var h:int = 2 + 52 * Math.random();
                var w:int = 2 + 52 * Math.random();
                var color:uint = Math.random() * 0xffffff;
                var bmd:BitmapData = new BitmapData(w, h, false, color);
                bmd.fillRect(new Rectangle(1, 1, w-2, h-2), color >> 1 & 0x7f7f7f);
                boxes[i] = new CMLMovieClipTexture(bmd);
            }
            var packedBmds:Array = pack(boxes, 465, 465);
            bmp.bitmapData = packedBmds[0];
        }

        /**
        *  @param textures textures to pack (textures' bitmapData and rect properties will be modified)
        *  @param width bin (packed bitmap) width
        *  @param height bin (packed bitmap) height
        *  @param destroyOriginals if true dispose() will be called on the textures' original bitmapData
        *  @return Array of bin (packed BitmapData objects)
        */
        public function pack(textures:Vector.<CMLMovieClipTexture>, width:uint = 2048, height:uint = 2048, destroyOriginals:Boolean = true):Array {
            var tex:CMLMovieClipTexture, ptn:CMLMovieClipTexture;
            var disposables:Array = [], patterns:Array = [], bmds:Array = [], bins:Array = [];
            var placement:PackerNode;

            for each(tex in textures) {
                for each(ptn in tex.animationPattern) {
                    if(patterns.indexOf(ptn) == -1) patterns.push(ptn);
                }
            }
            for each(tex in patterns) {
                if(tex.width>width || tex.height>height) throw(new Error("Texture larger than requested bin size."));
                if(destroyOriginals && disposables.indexOf(tex.bitmapData) == -1) disposables.push(tex.bitmapData);
                var i:int = 0;
                while(i < bins.length && (placement = bins[i].place(tex)) == null) i++;
                if(!placement) {
                    bins[i] = new PackerNode(0, 0, width, height);
                    bmds[i] = new BitmapData(width, height, false, 0);
                    placement = bins[i].place(tex);
                }
                bmds[i].copyPixels(tex.bitmapData, tex.rect, placement.r.topLeft);
                tex.bitmapData = bmds[i];
                tex.rect = placement.r;
            }
            for each(var bmd:BitmapData in disposables) bmd.dispose();
            return bmds;
        }
    }
}

import flash.geom.*;

/** Recursive texture packer, based on http://www.blackpawn.com/texts/lightmaps/default.html */
class PackerNode {
    public var a:PackerNode, b:PackerNode;
    public var r:Rectangle;
    public var content:Object;

    public function PackerNode(x:Number, y:Number, width:Number, height:Number) { r = new Rectangle(x, y, width, height); }

    /**
    *  @param tex anything with width and height properties
    *  @return empty node with same dimensions as tex, or null on failure.
    */
    public function place(tex:Object):PackerNode {
        if(content || r.width < tex.width || r.height < tex.height) return null; // full or too small
        if(a) return(a.place(tex) || b.place(tex)); // not a leaf node, try placing in children
        if(r.width == tex.width && r.height == tex.height) { // exact fit
            content = tex;
            return this;
        }
        // too large - split this node
        var dw:Number = r.width - tex.width;
        var dh:Number = r.height - tex.height;
        if(dw > dh) {
            a = new PackerNode(r.x, r.y, tex.width, r.height);
            b = new PackerNode(r.x+tex.width, r.y, dw, r.height);
        } else {
            a = new PackerNode(r.x, r.y, r.width, tex.height);
            b = new PackerNode(r.x, r.y+tex.height, r.width, dh);
        }
        return a.place(tex);
    }
}