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

Elastic Image

@author Saqoosha
Get Adobe Flash player
by Saqoosha 29 Feb 2012
/**
 * Copyright Saqoosha ( http://wonderfl.net/user/Saqoosha )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/poFZ
 */

package {

    import com.bit101.components.CheckBox;
    import com.bit101.components.HUISlider;
    import com.bit101.components.PushButton;
    import com.bit101.components.VBox;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;


    /**
     * @author Saqoosha
     */
    [SWF(backgroundColor="0xFFFFFF", frameRate="60", width="1024", height="768")]
    public class ElasticImage extends Sprite {
        
        
        private var _numSegments:int = 20;
        private var _segmentLength:Number = 10;
        
        private var _segmentsSlider:HUISlider;
        private var _dragSlider:HUISlider;
        private var _debugCheckBox:CheckBox;
        
        private var _dragging:Anchor = null;
        private var _anchors:Vector.<Anchor>;
        
        private var _image:BitmapData;
        private var _vertices:Vector.<Number>;
        private var _indices:Vector.<int>;
        private var _uvtData:Vector.<Number>;
        
        
        public function ElasticImage() {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.quality = StageQuality.LOW;
            
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _onImageLoaded);
            loader.load(new URLRequest('http://saqoo.sh/a/tmp/Saqoosha256.png'), new LoaderContext(true));
        }


        private function _onImageLoaded(e:Event):void {
            _image = Bitmap(LoaderInfo(e.target).content).bitmapData;
            
            var vbox:VBox = new VBox(this, 10, 10);
            _segmentsSlider = new HUISlider(vbox, 0, 0, 'NUM SEGMENTS');
            _segmentsSlider.minimum = 3;
            _segmentsSlider.maximum = 20;
            _segmentsSlider.value = 8;
            _segmentsSlider.tick = 1;
            _segmentsSlider.labelPrecision = 0;
            _segmentsSlider.width = 300;
            new PushButton(vbox, 0, 0, 'REBUILD', _onClickRebuild);
            _dragSlider = new HUISlider(vbox, 0, 0, 'DRAG');
            _dragSlider.minimum = 0.1;
            _dragSlider.maximum = 0.9;
            _dragSlider.value = 0.5;
            _dragSlider.tick = 0.01;
            _dragSlider.labelPrecision = 2;
            _dragSlider.width = 300;
            _debugCheckBox = new CheckBox(vbox, 0, 0, 'DEBUG');
            _debugCheckBox.selected = false;
            
            _onClickRebuild();
            
            stage.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
            addEventListener(Event.ENTER_FRAME, _draw);
        }


        private function _onClickRebuild(e:Event = null):void {
            _numSegments = _segmentsSlider.value;
            _segmentLength = 200 / (_numSegments - 1);
            _anchors = new Vector.<Anchor>();
            _vertices = new Vector.<Number>();
            _indices = new Vector.<int>();
            _uvtData = new Vector.<Number>();
            var n:int = _numSegments - 1;
            var x:int, y:int;
            for (y = 0; y < _numSegments; y++) {
                for (x = 0; x < _numSegments; x++) {
                    _anchors.push(new Anchor(x * _segmentLength, y * _segmentLength));
                    _vertices.push(0, 0);
                    if (x > 0 && y > 0) {
                        var index:int = x + y * _numSegments;
                        _indices.push(index - _numSegments - 1, index - _numSegments, index - 1);
                        _indices.push(index - _numSegments, index, index - 1);
                    }
                    _uvtData.push(x / n, y / n);
                }
            }
            _retargetAnchors(_anchors[0]);
        }
        
        
        private function _onMouseDown(e:MouseEvent):void {
            if (e.target != stage) return;
            stage.addEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
            stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
            
            var minDist:Number = Number.MAX_VALUE;
            for each (var a:Anchor in _anchors) {
                var dx:Number = mouseX - a.x;
                var dy:Number = mouseY - a.y;
                var d:Number = dx * dx + dy * dy;
                if (d < minDist) {
                    _dragging = a;
                    minDist = d;
                }
            }
            _retargetAnchors(_dragging);
            _dragging.x = mouseX;
            _dragging.y = mouseY;
        }


        private function _onMouseMove(e:MouseEvent):void {
            _dragging.x = mouseX;
            _dragging.y = mouseY;
        }


        private function _onMouseUp(e:MouseEvent):void {
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);
            stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
            _dragging = null;
        }
        
        
        private function _retargetAnchors(origin:Anchor):void {
            origin.target = null;
            var x:int, y:int;
            for (y = 0; y < _numSegments; y++) {
                for (x = 0; x < _numSegments; x++) {
                    var index:int = y * _numSegments + x;
                    var a:Anchor = _anchors[index];
                    if (a == origin) continue;
                    var dx:int = a.x - origin.x;
                    var dy:int = a.y - origin.y;
                    if (Math.abs(dx) > Math.abs(dy)) {
                        if (dx > 0) {
                            a.target = _anchors[index - 1];
                            a.offsetX = _segmentLength;
                        } else {
                            a.target = _anchors[index + 1];
                            a.offsetX = -_segmentLength;
                        }
                        a.offsetY = 0;
                    } else {
                        if (dy > 0) {
                            a.target = _anchors[index - _numSegments];
                            a.offsetY = _segmentLength;
                        } else {
                            a.target = _anchors[index + _numSegments];
                            a.offsetY = -_segmentLength;
                        }
                        a.offsetX = 0;
                    }
                }
            }
        }
        
        
        private function _draw(e:Event = null):void {
            var a:Anchor;
            var index:int = 0;
            var drag:Number = _dragSlider.value;
            for (var i:int = 0, n:int = _anchors.length; i < n; i++) {
                a = _anchors[i];
                if (a.target) {
                    a.x += (a.target.x + a.offsetX - a.x) * drag;
                    a.y += (a.target.y + a.offsetY - a.y) * drag;
                }
                _vertices[index++] = a.x;
                _vertices[index++] = a.y;
            }
            
            graphics.clear();
            graphics.beginBitmapFill(_image);
            graphics.drawTriangles(_vertices, _indices, _uvtData);
            graphics.endFill();
            if (_debugCheckBox.selected) {
                for each (a in _anchors) {
                    if (a.target) {
                        graphics.lineStyle(0, 0x7c93ff);
                        graphics.moveTo(a.x, a.y);
                        graphics.lineTo(a.x + (a.target.x - a.x) * .5, a.y + (a.target.y - a.y) * .7);
                        graphics.lineStyle();
                    }
                    graphics.beginFill(0xff487b);
                    graphics.drawCircle(a.x, a.y, 3);
                    graphics.endFill();
                }
            }
        }
    }
}


class Anchor {
    
    
    public var x:Number;
    public var y:Number;
    public var target:Anchor = null;
    public var offsetX:Number = 0;
    public var offsetY:Number = 0;


    public function Anchor(x:Number = 0, y:Number = 0, target:Anchor = null) {
        this.y = y;
        this.x = x;
        this.target = target;
        if (target) {
            offsetX = x - target.x;
            offsetY = y - target.y;
        }
    }
}