<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" 
    backgroundColor="#333333" 
    creationComplete="onCreationComplete()">
    
    <mx:Script>
        <![CDATA[
            
            import mx.controls.Image;
            import org.flashsandy.display.*;
            
            private var shape:Shape = new Shape();
            private var distortion:DistortImage = new DistortImage(500, 375, 3, 3);
            private var showGrid:Boolean = false;
            
            // * The following 3 properties were not in the original demo (rubenswieringa.com/code/as3/flex/DistortImage):
            private var image:Image = new Image();
            private var bitmapData:BitmapData;
            private var preparationRecursion:int = 0;
            
            private function onCreationComplete ():void {
                this.shape.x = this.shape.y = 50;
                this.rawChildren.addChild(this.shape);
                this.image.visible = false;
                this.addChildAt(this.image, 0);
                this.loadImage();
            }
            
            private function onEnterFrame (event:Event=null):void {
                this.shape.graphics.clear();
                if (this.showGrid || this.showGridCheckbox.selected){
                    this.shape.graphics.lineStyle(1, 0x00FF00);
                }
                distortion.setTransform(this.shape.graphics, 
                                        this.bitmapData, 
                                        this.getDisplayObjectCenter(this.dragBtn1, -50, -50), 
                                        this.getDisplayObjectCenter(this.dragBtn2, -50, -50), 
                                        this.getDisplayObjectCenter(this.dragBtn3, -50, -50), 
                                        this.getDisplayObjectCenter(this.dragBtn4, -50, -50));
            }
            
            private function getDisplayObjectCenter (child:DisplayObject, x:Number=0, y:Number=0):Point {
                var center:Point = new Point();
                center.x = child.x + child.width/2 + x;
                center.y = child.y + child.height/2 + y;
                return center;
            }
            
            // * This method was not in the original demo (rubenswieringa.com/code/as3/flex/DistortImage):
            private function loadImage ():void {
                image.addEventListener(Event.COMPLETE,    this.prepareDistortion);
                image.load("assets/img/invaderzim.jpg");
            }
            
            // * This method was not in the original demo (rubenswieringa.com/code/as3/flex/DistortImage):
            private function prepareDistortion (event:Event=null):void {
                // if this method has called itself for more than 25 times something must be wrong:
                this.preparationRecursion++;
                if (this.preparationRecursion >= 25){
                    return;
                }
                // if the Image isn't there yet then try again in a bit:
                if (this.image.width == 0){
                    callLater(this.prepareDistortion);
                    return;
                }
                // fetch BitmapData:
                this.bitmapData = new BitmapData(image.width, image.height);
                this.bitmapData.draw(this.image);
                // remove Image from Stage and start calling the onEnterFrame() method:
                this.removeChild(this.image);
                this.addEventListener(Event.ENTER_FRAME, this.onEnterFrame);
            }
            
        ]]>
    </mx:Script>
    
    <mx:Style>
        Button {
            upSkin: Embed('assets/skins/drag.swf');
            overSkin: Embed('assets/skins/drag.swf');
            downSkin: Embed('assets/skins/drag.swf');
            disabledSkin: Embed('assets/skins/drag.swf');
        }
    </mx:Style>
    
    <mx:Button id="dragBtn1" x="47"  y="47"  buttonMode="true" mouseDown="dragBtn1.startDrag()" mouseUp="dragBtn1.stopDrag()" />
    <mx:Button id="dragBtn2" x="547" y="47"  buttonMode="true" mouseDown="dragBtn2.startDrag()" mouseUp="dragBtn2.stopDrag()" />
    <mx:Button id="dragBtn3" x="547" y="422" buttonMode="true" mouseDown="dragBtn3.startDrag()" mouseUp="dragBtn3.stopDrag()" />
    <mx:Button id="dragBtn4" x="47"  y="422" buttonMode="true" mouseDown="dragBtn4.startDrag()" mouseUp="dragBtn4.stopDrag()" />
    
    <mx:CheckBox 
        id="showGridCheckbox" 
        x="80" y="442" 
        toolTip="Show grid" />
    <mx:HSlider 
        id="precisionSlider" 
        x="100" y="440" width="400" 
        value="3" 
        minimum="1" maximum="5" 
        liveDragging="true" snapInterval="1" 
        mouseDown="showGrid=true" mouseUp="showGrid=false" 
        change="distortion.setPrecision(precisionSlider.value, precisionSlider.value)" />
    
</mx:Application>