<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx ="http://www.adobe.com/2006/mxml"
                layout ="absolute" 
                applicationComplete ="init()" 
                backgroundColor ="0x707070" 
                name ="CubicSpace"
                viewSourceURL ="srcview/index.html"> 
    
    <!-- by Petri Leskinen, Espoo, Finland, May 2011  -->
    
    
    <mx:Script>
        <![CDATA[ 
            
            
            import filter.CubicSpaceFilter;
            
            import flash.display.Bitmap;
            import flash.display.BitmapData;
            import flash.display.Sprite;
            import flash.events.Event;
            import flash.events.KeyboardEvent;
            
            import mx.controls.HSlider;
            import mx.controls.Label;
            import mx.controls.Spacer;
            import mx.controls.TextArea;
            import mx.controls.sliderClasses.Slider;
            import mx.core.UIComponent;
            import mx.events.SliderEvent;
            
            import net.*;
            
            
            
            /**    the shader class */
            [Bindable("change")]
            protected var cubicSpace:CubicSpaceFilter = new CubicSpaceFilter(null,null);
            
            
            /** Embedded images */
            [Embed( '../assets/Circle.png')]
            protected var Picture1:Class;
            
            [Embed( '../assets/YellowRoses.png')]
            protected var Picture2:Class;
            
            [Embed( '../assets/BarbFrame.png')]
            protected var Picture3:Class;
            
            [Embed( '../assets/Frame3B.png')]
            protected var Picture4:Class;
            
            [Embed('../assets/Frame.png')]
            protected var Picture5:Class;
            
            [Embed('../assets/Frame3.png')]
            protected var Picture6:Class;
            
            [Embed('../assets/Cubics01.png')]
            protected var Picture7:Class;
            
            [Embed('../assets/Cubics02.png')]
            protected var Picture9:Class;
            
            [Embed('../assets/Cubics03.png')]
            protected var Picture10:Class;
            
            [Embed('../assets/Frame8.png')]
            protected var Picture8:Class;
            
            
            /**    Parameters for animation */
            private var 
                animated:Boolean = false,    
                frameCount:uint =20,
                frameMatrix:Matrix3D =new Matrix3D()
                ;
            
            
            /**    Inits the application */
            protected function init():void {
                
                cubicSpace.output = new BitmapData(600,280,false);
                UIRef.addChild(new Bitmap(cubicSpace.output));
                
                cubicSpace.colorX    =0xFFFFFF;
                cubicSpace.colorY    =0x333333;
                cubicSpace.colorZ    =0x666666;
                cubicSpace.bgcolor    =0x999999;
                initImage();
                
                addEventListener(Event.ENTER_FRAME, this.animate);
                stage.addEventListener(FullScreenEvent.FULL_SCREEN, this.enterFullScreen);
                stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown, true, 1, true);
                stage.focus=UIRef;
            }
            
            
            /**    Changes to the image selected in ComboBox 
             * */
            protected function initImage():void {
                var c:Class;
                switch (imageCombo.selectedLabel) {
                    case "Frame 1":
                        c =Picture5;
                        break;
                    
                    case "Gradient":
                        c =Picture6;
                        break;
                    
                    case "Circle": 
                        c =Picture1;
                        break;
                    case "Gradient 3":
                        c =Picture4;
                        break;
                    
                    case "Gradient 2":
                        c =Picture8;
                        break;
                    
                    case "Cubics 1":
                        c =Picture7;
                        break;
                    
                    case "Cubics 2":
                        c =Picture9;
                        break;
                    
                    case "Cubics 3":
                        c =Picture10;
                        break;
                    
                    case "Barbwire":
                        cubicSpace.input=null;
                        cubicSpace.colorX=cubicSpace.colorY=0x800000;
                        cubicSpace.colorZ=0xA00000;
                        cubicSpace.bgcolor=0xFFFFFF;
                        c =Picture3;
                        break;
                    
                    case "Yellow Roses":
                        cubicSpace.input=null;
                        cubicSpace.colorX=cubicSpace.colorY=0xFFFFFF;
                        cubicSpace.colorZ=0xEEEEEE;
                        cubicSpace.bgcolor=0;
                        c =Picture2;
                        break;
                    
                    case "... Browse":
                        uploadImage();
                        return;
                }
                initSource(Bitmap(new c).bitmapData);
            }
            
            
            //    not used in this appl. but leaves some empty area as image borders
            private var padding:int=0;
            
            
            /**    change the source image */
            protected function initSource(source:BitmapData):void {
                
                var bmd:BitmapData = new BitmapData(source.width+2*padding,source.height+2*padding, true,0);
                bmd.draw(source, new Matrix(1,0,0,1,padding,padding));
                
                //    set filter input
                cubicSpace.input = bmd;
                //    update preview thumbnail on controls
                sourcePreview.source = new Bitmap(source);
                
            }
            
            
            /**    Apply rotation, angles by mouse position */
            private function canvasClicked(e:MouseEvent):void {
                if (!animated) {
                    var ex:Number = e.localX/cubicSpace.output.width-0.5,
                        ey:Number = 0.5-e.localY/cubicSpace.output.height;
                    cubicSpace.rotateToRight(30*ex);
                    cubicSpace.rotateUpwards(30*ey);
                }
            }
            
            
            /**    Handles switching to full screen and back */
            private function enterFullScreen(e:FullScreenEvent):void {
                //    toggle control panel visibility
                this.controls.visible=!e.fullScreen;
                if (e.fullScreen) {
                    //    scale image canvas to fill whole stage
                    this.x=-UIRef.x -30; 
                    this.y=-UIRef.y +10; 
                    UIRef.scaleX = UIRef.scaleY = stage.fullScreenWidth/cubicSpace.output.width;
                    animated = true;
                } else {
                    //    scale canvas back to original size
                    x = y = 0;
                    UIRef.scaleX = UIRef.scaleY = 1;
                }
            }
            
            
            /**    Frame update for animation */
            private function animate(e:Event):void {
                if (!animated) return;
                
                //    frameMatrix, small 'step' consisting of translation and rotation, taken each frame
                cubicSpace.m.prepend(frameMatrix);
                cubicSpace.moveForward(0);
                
                frameCount++;
                
                //    when frameCount reaches 20, we change the direction:
                if (frameCount>19) {
                    
                    cubicSpace.viewpointX = cubicSpace.viewpointX %cubicSpace.size;
                    cubicSpace.viewpointY = cubicSpace.viewpointY %cubicSpace.size;
                    cubicSpace.viewpointZ = cubicSpace.viewpointZ %cubicSpace.size;
                    
                    frameCount=0;
                    frameMatrix =new Matrix3D();
                    
                    //    Whole rotation is always 90 degress taken in 20 steps:
                    var f:Number = 90/20;
                    
                    //    Randomly choose the new moves:
                    switch(int(6*Math.random())) {
                        
                        case 0:
                            //    rotate to left
                            frameMatrix.appendTranslation(0,-cubicSpace.size/2,0);
                            frameMatrix.prependRotation(-f, Vector3D.Z_AXIS);
                            frameMatrix.prependTranslation(0,cubicSpace.size/2,0);
                            break;
                        
                        case 1:
                            //    rotate to right:
                            frameMatrix.appendTranslation(0,cubicSpace.size/2,0);
                            frameMatrix.prependRotation(f, Vector3D.Z_AXIS);
                            frameMatrix.prependTranslation(0,-cubicSpace.size/2,0);
                            break;
                        
                        case 2:
                            //    rotate upwards
                            frameMatrix.appendTranslation(0,0,-cubicSpace.size/2);
                            frameMatrix.prependRotation(f, Vector3D.Y_AXIS);
                            frameMatrix.prependTranslation(0,0,cubicSpace.size/2);
                            break;
                        
                        case 3:
                            //    rotate downwards
                            frameMatrix.appendTranslation(0,0,cubicSpace.size/2);
                            frameMatrix.prependRotation(-f, Vector3D.Y_AXIS);
                            frameMatrix.prependTranslation(0,0,-cubicSpace.size/2);
                            break;
                        
                        case 4:
                            //    forward, rotate around viewdirection:
                            frameMatrix.prependTranslation(cubicSpace.size/20,0,0);
                            frameMatrix.prependRotation(Math.random()<0.5 ? f : -f, Vector3D.X_AXIS);
                            break;
                        
                        default:
                            //    move forward
                            frameMatrix.prependTranslation(cubicSpace.size/20,0,0);
                    }
                }
            }
            
            
            /**    Movement by keyboard press */
            private function keyDown(e:KeyboardEvent):void {
                laabeli.text= "char: "+e.charCode+    ", key: "+e.keyCode;
                switch (e.keyCode) {
                    case Keyboard.LEFT:
                        this.cubicSpace.rotateToRight(-10);
                        break;
                    case Keyboard.RIGHT:
                        this.cubicSpace.rotateToRight(10);
                        break;
                    case Keyboard.UP:
                        this.cubicSpace.moveForward(10);
                        break;
                    case Keyboard.DOWN:
                        this.cubicSpace.moveForward(-10);
                        break;
                }
            }
                
            
            /**    upload an image from local computer */
            private function uploadImage():void {
                //    initSource as parameter is the function to call when upload is ready
                new ImageFormatImporter(initSource);
                imageCombo.selectedIndex=-1;
            }
            
            
            /**    save .png to local computer */
            private function savePNG():void {
                new PngFormatExporter(cubicSpace.output, this.name+".png");
            }
            
            
            /**    save .jpg to local computer */
            private function saveJPG():void {
                new JpgFormatExporter(cubicSpace.output, this.name+".jpg");
            }
            
            
            
        ]]>
        
    </mx:Script>
    
    <mx:HBox x="30" y="30">
        
        <mx:Panel id="controls" label="Disks" headerHeight="0" borderColor="0xD0D0D0" >
            
            <mx:VBox x="20" y="40" horizontalAlign="center" verticalGap="5" 
                     width="170" height="700" backgroundColor="0x505050"> 
                
                <mx:Spacer height="20" /> 
                
                <mx:ComboBox 
                    id="imageCombo" width="150" 
                    change="initImage()" rowCount="12" 
                    
                    selectedIndex="0"
                    prompt="Select an Image"> 
                    <mx:ArrayCollection>
                        <mx:Object label="Frame 1" />
                        <mx:Object label="Gradient" />
                        <mx:Object label="Gradient 2" />
                        <mx:Object label="Gradient 3" />
                        <mx:Object label="Circle" />
                        <mx:Object label="Cubics 1" />
                        <mx:Object label="Cubics 2" />
                        <mx:Object label="Cubics 3" />
                        <mx:Object label="Yellow Roses" />
                        <mx:Object label="Barbwire" />
                        <mx:Object label="... Browse" />
                        
                    </mx:ArrayCollection>
                </mx:ComboBox>
                
                <mx:Spacer height="5" /> 
                
                <mx:Image id="sourcePreview" width="128" height="128"
                          click="/*tiling.output.fillRect(tiling.output.rect,0);tiling.output.draw(sourcePreview.source as Bitmap)*/" 
                          />
                
                
                    <mx:Label text="Colors:" />
                <mx:HBox>
                    <mx:ColorPicker selectedColor="@{cubicSpace.colorX}" change="cubicSpace.colorX=event.color" />
                    <mx:ColorPicker selectedColor="@{cubicSpace.colorY}" change="cubicSpace.colorY=event.color" />
                    <mx:ColorPicker selectedColor="@{cubicSpace.colorZ}" change="cubicSpace.colorZ=event.color" />
                    <mx:Spacer width="5" />
                    <mx:ColorPicker selectedColor="@{cubicSpace.bgcolor}" change="cubicSpace.bgcolor=event.color" />
                </mx:HBox>    
                
                
                <mx:HSlider value="@{cubicSpace.viewpointX}" minimum="-100" maximum="200"
                            change="cubicSpace.viewpointX=event.value;" liveDragging="true" 
                            labels="['','View Point','']" labelOffset="0" width="150"
                            />
                
                <mx:HSlider value="@{cubicSpace.viewpointY}" minimum="-100" maximum="200" width="150"
                            change="cubicSpace.viewpointY=event.value;" liveDragging="true" 
                            />
                
                <mx:HSlider value="@{cubicSpace.viewpointZ}" minimum="-100" maximum="200" width="150"
                            change="cubicSpace.viewpointZ=event.value;" liveDragging="true" 
                            />
                
                
                <mx:HSlider minimum="-90" value="@{cubicSpace.rotation}" maximum="90"
                            change="cubicSpace.rotation=event.value;" liveDragging="true" snapInterval="1"
                            labels="['','Rotation','']" labelOffset="0" width="150"
                            />
                
                <mx:HSlider minimum="-90" value="@{cubicSpace.tilt}" maximum="90"
                            change="cubicSpace.tilt=event.value;" liveDragging="true" snapInterval="1"
                            labels="['','Tilt','']" labelOffset="0" width="150"
                            />
                
                <mx:Spacer height="8" /> 
                
                <mx:CheckBox id="qualityCB" label="Fast / Deeper View" labelPlacement="left" 
                             click="cubicSpace.quality=qualityCB.selected" />
                
                
                <mx:Spacer height="8" /> 
                
                <mx:HSlider minimum="40" value="@{cubicSpace.focalLength}" maximum="600"
                            change="cubicSpace.focalLength=event.value;" liveDragging="true"
                            labels="['','Focal Length','']" labelOffset="0" width="150"
                            />
                
                <mx:HSlider minimum="0.2" value="@{cubicSpace.fade}" maximum="1"
                            change="cubicSpace.fade=event.value;" 
                            liveDragging="true" width="150" snapInterval="0.01"
                            labels="['','Fade','']" labelOffset="0"    
                            />
                
                <mx:Spacer height="8" /> 
                
                <mx:Button label="Animated"  width="150" click="animated=!animated" />
                
                <mx:Button label="Full Screen" width="150"
                           click="this.stage.displayState=flash.display.StageDisplayState.FULL_SCREEN;" />
                
                <mx:Spacer height="20" /> 
                
                <mx:HBox>
                    <mx:Button label="Save as .png" width="96" click="savePNG();" />
                    <mx:Button label=".jpg" width="45" click="saveJPG()" />
                </mx:HBox>
                
            </mx:VBox>
        </mx:Panel>
        
        <mx:Spacer width="50" />
        
        <!--    container for image -->
        <mx:UIComponent id="UIRef" />
        
        <!--    label for testing output -->
        <mx:Label id="laabeli" visible="false" />
        
    </mx:HBox>
    
</mx:Application>