<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" frameRate="120" backgroundColor="0" backgroundGradientAlphas="[0, 0]" viewSourceURL="srcview/index.html">
    <mx:Script>
        <![CDATA[
        
            private var _shader : Shader;
            private var _shaderFilter : ShaderFilter;
            
            /*
             * The exported PixelBender kernel (see PixelBender source for the exact implementation)
             */
            [Embed(source="waterBuffer.pbj", mimeType="application/octet-stream")]
            private var _shaderObj : Class;
            
            
            private var _damping : Number = 1.0;
            
            /*
             * The buffers between which we'll be swapping
             */
            private var _buffer1 : BitmapData;
            private var _buffer2 : BitmapData;
            
            /*
             * References to the bitmap for easier swapping
             */
            private var _activeBitmap : BitmapData;
            private var _nonActiveBitmap : BitmapData;
            
            private var _displacement : DisplacementMapFilter;
            
            private function init() : void
            {
                // init clean bitmapdata
                _buffer1 = new BitmapData(picture.width, picture.height, false, 0);
                _buffer2 = new BitmapData(picture.width, picture.height, false, 0);
                
                _activeBitmap = _buffer1;
                _nonActiveBitmap = _buffer2;
                
                initFilter();
                
                // create a displacement filter based on PixelBender's generated image to deform the original image
                _displacement = new DisplacementMapFilter(_activeBitmap, new Point(0, 0), BitmapDataChannel.RED, BitmapDataChannel.RED, 40, 40, DisplacementMapFilterMode.WRAP);
                
                this.addEventListener(Event.ENTER_FRAME, handleEnterFrame);
            }
            
            /**
             * Initializes the PixelBender filter
             */
            private function initFilter() : void
            {
                // create instance of the embedded 
                _shader = new Shader(new _shaderObj());
                
                // set the parameters defined in the PixelBender kernel
                _shader.data.damping.value = [ _damping ];
                _shader.data.buffer2.input = _activeBitmap;
                _shader.data.buffer1.input = _nonActiveBitmap;
                
                // create filter from Shader
                _shaderFilter = new ShaderFilter( _shader );
            }
            
            /**
             * 
             */
            private function updateFilter() : void
            {
                _shader.data.buffer2.input = _activeBitmap;
                _shader.data.buffer1.input = _nonActiveBitmap;
                
                _activeBitmap.applyFilter(_activeBitmap, new Rectangle(0, 0, picture.width, picture.height), new Point(0, 0), _shaderFilter);
            }
            
            private function handleEnterFrame(event : Event) : void
            {
                /*
                 * Swaps bitmaps, so filter will alternatively run on either one, using the other to offset
                 */ 
                if (_activeBitmap == _buffer2) {
                    _activeBitmap = _buffer1;
                    _nonActiveBitmap = _buffer2;
                }
                else {
                    _activeBitmap = _buffer2;
                    _nonActiveBitmap = _buffer1;
                }
            
                _displacement.mapBitmap = _activeBitmap;
                picture.filters = [ _displacement ];
                
                updateFilter();
            }
            
            /**
             * Draw a small square at the position of the mouse
             */
            private function handleMouseMove(event : MouseEvent) : void
            {
                _activeBitmap.fillRect(new Rectangle(event.localX, event.localY, 10, 10), 0xffffff);
            }
        ]]>
    </mx:Script>
    <mx:Image horizontalCenter="0" verticalCenter="0" id="picture" source="@Embed(source='../embeds/images/bennylava_edge.jpg')" mouseMove="handleMouseMove(event)"/>
</mx:Application>