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

Pure AS3 Free Transform

Get Adobe Flash player
by Zebestov 28 Feb 2016

    Talk

    makc3d at 29 Feb 2016 00:35
    by Zeh?
    Zebestov at 29 Feb 2016 02:25
    No, but it was the similar way: "I was lucky enough to get what I wanted working after a good amount of crazy trial and error (and beer)". Well, except that it was coffee instead of beer… possibly that's why Zeh found theese proportions a year earlier! :)

    Tags

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

package  {
    import flash.system.LoaderContext;
    import flash.events.ErrorEvent;
    import flash.events.Event;
    import flash.display.Loader;
    import flash.net.URLRequest;
    import flash.display.LoaderInfo;
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.geom.Rectangle;
    import flash.geom.Point;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.text.TextFormat;
    import flash.text.AntiAliasType;
    import flash.text.TextFormatAlign;
    import flash.display.StageQuality;
    import flash.geom.Matrix;
    import flash.display.GradientType;

    public class Main extends Sprite {

        private var image:BitmapData;
        private var canvas:Shape = new Shape();
        private var marker0:Sprite, marker1:Sprite, marker2:Sprite, marker3:Sprite;
        private var p0:Point, p1:Point, p2:Point, p3:Point;
        private var currentDraggable:Sprite;

        public function Main() {
            stage.quality = StageQuality.BEST;

            var mtx:Matrix = new Matrix();
            mtx.createGradientBox(stage.stageWidth, stage.stageHeight * 2, -45, 0, 0);

            var background:Shape = new Shape();
            background.graphics.beginGradientFill(GradientType.LINEAR, [0x666666, 0xa9b5cd], [1.0, 1.0],[0, 255], mtx);
            background.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            background.graphics.endFill();
            addChild(background);

            loadImage();
        }

        private function start():void {
            addChild(canvas);
            p0 = new Point();
            p1 = new Point();
            p2 = new Point();
            p3 = new Point();

            var sw:int = stage.stageWidth;
            var sh:int = stage.stageHeight;
            var scale:Number = Math.min((sw - 100) / image.width, (sh - 50) / image.height);
            var rect:Rectangle = new Rectangle((sw - image.width * scale) / 2, (sh - image.height * scale) / 2, image.width * scale, image.height * scale);

            marker0 = createMarker('1', rect.left, rect.top);
            marker1 = createMarker('2', rect.right, rect.top);
            marker2 = createMarker('3', rect.right, rect.bottom);
            marker3 = createMarker('4', rect.left, rect.bottom);

            addChild(marker0);
            addChild(marker1);
            addChild(marker2);
            addChild(marker3);

            stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpOrLeave);
            stage.addEventListener(Event.MOUSE_LEAVE, onMouseUpOrLeave);
            stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }



        private function onEnterFrame(event:Event):void {
            p0.x = marker0.x;
            p0.y = marker0.y;
            p1.x = marker1.x;
            p1.y = marker1.y;
            p2.x = marker2.x;
            p2.y = marker2.y;
            p3.x = marker3.x;
            p3.y = marker3.y;

            var convexTest1:Boolean = isConvex(p3, p0, p1);
            var convexTest2:Boolean = isConvex(p0, p1, p2);
            var convexTest3:Boolean = isConvex(p1, p2, p3);
            var convexTest4:Boolean = isConvex(p2, p3, p0);

            if (convexTest1 == convexTest3 && convexTest2 == convexTest4) {
                freeTransform(image, canvas, p0, p1, p2, p3, true);
            }
        }

        private function onMouseDown(event:MouseEvent):void {
            var target:Sprite = event.target as Sprite;
            if (target.name == 'marker') {
                addChild(target);
                currentDraggable = target;
                target.startDrag(false, stage.getBounds(stage));
            }
        }

        private function onMouseUpOrLeave(event:Event):void {
            if (currentDraggable) {
                currentDraggable.stopDrag();
                currentDraggable = null;
            }
        }

        private function freeTransform(image:BitmapData, canvas:Shape, p1:Point, p2:Point, p3:Point, p4:Point, clear:Boolean = false):void {
            var diagonalRatio:Number = Point.distance(p1, p3) / Point.distance(p2, p4);

            var a1:Number = p1.y - p3.y;
            var b1:Number = p3.x - p1.x;
            var c1:Number = p1.x * p3.y - p3.x * p1.y;
            var a2:Number = p2.y - p4.y;
            var b2:Number = p4.x - p2.x;
            var c2:Number = p2.x * p4.y - p4.x * p2.y;

            var intersection:Point = new Point((c2*b1-c1*b2)/(a1*b2-a2*b1), (a2*c1-a1*c2)/(a1*b2-a2 * b1));
            var t1:Number = 1 / Point.distance(p3, intersection) * diagonalRatio;
            var t2:Number = 1 / Point.distance(p4, intersection);
            var t3:Number = 1 / Point.distance(p1, intersection) * diagonalRatio;
            var t4:Number = 1 / Point.distance(p2, intersection);

            var vertices:Vector.<Number> = new Vector.<Number>();
            vertices.push(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
            var indices:Vector.<int> = new Vector.<int>();
            indices.push(0, 1, 2, 2, 3, 0);
            var uvtdata:Vector.<Number> = new Vector.<Number>();
            uvtdata.push(0, 0, t1, 1, 0, t2, 1, 1, t3, 0, 1, t4);

            if (clear) {
                canvas.graphics.clear();
            }

            canvas.graphics.beginBitmapFill(image, null, false, true);
            canvas.graphics.drawTriangles(vertices, indices, uvtdata);
            canvas.graphics.endFill();
        }

        private function isConvex(p1:Point, p2:Point, p3:Point):Boolean {
            var a:Point = new Point(p1.x - p2.x, p1.y - p2.y);
            var b:Point = new Point(p3.x - p2.x, p3.y - p2.y);
            return ((a.x * b.y - a.y * b.x) <= 0);
        }

        private function createMarker(label:String, x:int, y:int):Sprite {
            var result:Sprite = new Sprite();
            result.graphics.lineStyle(1, 0xffffff);
            result.graphics.beginFill(0x3399ff);
            result.graphics.drawCircle(0, 0, 10);
            result.graphics.endFill();

            var tfld:TextField = new TextField();
            tfld.defaultTextFormat = new TextFormat('Arial', 14, 0xffffff, true, null, null, null, null, TextFormatAlign.CENTER);
            tfld.text = label;
            tfld.width = 20;
            tfld.height = 20;
            tfld.x = -10;
            tfld.y = -10;
            result.addChild(tfld);

            result.x = x;
            result.y = y;
            result.name = 'marker';
            result.mouseChildren = false;
           
            return result;
        }

        private function loadImage():void {
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
            loader.load(new URLRequest('http://assets.wonderfl.net/images/related_images/4/47/4786/478610286ba93f45518f4f2e9d0bf0326035cc1b'), new LoaderContext(true));
        }

        private function onLoadComplete(event:Event):void {
            (event.target as LoaderInfo).removeEventListener(Event.COMPLETE, onLoadComplete);
            image = ((event.target as LoaderInfo).content as Bitmap).bitmapData;
            start();
        }
    }
}