package nu.xero.gui { import caurina.transitions.*; import flash.display.*; import flash.events.*; import flash.geom.*; import flash.media.*; import flash.net.*; import org.papervision3d.cameras.*; import org.papervision3d.core.render.data.*; import org.papervision3d.events.*; import org.papervision3d.materials.*; import org.papervision3d.objects.*; import org.papervision3d.objects.primitives.*; import org.papervision3d.view.*; public class coverflow extends BasicView { public var stats :RenderStatistics private var thisCover :DisplayObject3D private var theCovers :Array = new Array(); private var coverCount :Number; private var currentIndex :Number = 0; private var planeAngle :Number = 65; private var planeSeparation :Number = 100; private var planeOffset :Number = 200; private var needsRendered :Boolean = false; private var audio :Sound; private var isPlaying :Boolean = false; public function coverflow(playlist:XMLList, art:Array, stageRef:Stage) { super(0,0, true, true, CameraType.TARGET); camera.zoom = 1; camera.focus = 500; camera.z = -800; stats = renderer.renderScene(scene, camera, viewport); coverCount = playlist.length(); var i:Number = 0; while(i++ < coverCount) { theCovers[i] = new Object(); theCovers[i].cover = new Plane(new BitmapMaterial(generateReflection(art[i-1].img)), 461, 492, 4, 4); theCovers[i].cover.name = playlist[i-1].title; theCovers[i].cover.material.interactive = true; theCovers[i].cover.material.doubleSided = false; theCovers[i].cover.material.smooth = false; theCovers[i].cover.extra = i; theCovers[i].cover.y -= 200; theCovers[i].isZoomed = false; theCovers[i].mp3 = playlist[i-1].mp3; theCovers[i].cover.addEventListener(InteractiveScene3DEvent.OBJECT_MOVE, hover); theCovers[i].cover.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, hit); theCovers[i].cover.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, out); stageRef.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheel); scene.addChild(theCovers[i].cover, "cover"+i); } flowCovers(int(coverCount*.5+1)); startRendering(); } override protected function onRenderTick(e:Event = null):void { if(needsRendered){ super.onRenderTick(e); needsRendered=false; } } private function hit(e:InteractiveScene3DEvent):void { if(e.y <= 250){ //dont click the reflections thisCover = e.displayObject3D; flowCovers(thisCover.extra); } } private function hover(e:InteractiveScene3DEvent):void { if(e.y <= 250){ //dont click the reflections this.buttonMode = true; } else { this.buttonMode = false; } } private function out(e:InteractiveScene3DEvent):void { this.buttonMode = false; } private function mouseWheel(e:MouseEvent):void { if(e.delta < 0){ if(currentIndex > 1){ flowCovers(currentIndex-1); } } else { if (currentIndex < coverCount) { flowCovers(currentIndex+1); } } } private function generateReflection(bmp:BitmapData):BitmapData{ var reflectedBmp:BitmapData = new BitmapData(bmp.width, bmp.height*2, false, 0); reflectedBmp.draw(bmp); var alpha:Number = 0.3; var flipMatrix:Matrix = new Matrix(1, 0, 0, -1, 0, bmp.height*2 + 4); reflectedBmp.draw(bmp, flipMatrix, new ColorTransform(alpha, alpha, alpha, 1, 0, 0, 0, 0)); var holder:Shape = new Shape(); var gradientMatrix:Matrix = new Matrix(); gradientMatrix.createGradientBox(bmp.width, bmp.height, Math.PI*.5); holder.graphics.beginGradientFill(GradientType.LINEAR, [ 0, 0 ], [ 0, 100 ], [ 0, 0xFF ], gradientMatrix); holder.graphics.drawRect(0, 0, bmp.width, bmp.height); holder.graphics.endFill(); var m:Matrix = new Matrix(); m.translate(0, bmp.height); reflectedBmp.draw(holder, m); return reflectedBmp; } private function loadTrack(url:String):void { if(isPlaying) { SoundMixer.stopAll(); audio = null; } else { isPlaying = true; } audio = new Sound(new URLRequest(url), new SoundLoaderContext(5000)); audio.play(); } private function flowCovers(newIndex:*):void { if(currentIndex != newIndex) { needsRendered=true; var i:Number = 0; while(++i<=coverCount){ thisCover = theCovers[i].cover; theCovers[i].isZoomed = false; //smoothing if(i>=newIndex-1 && i<=newIndex+1) { thisCover.material.smooth = true; } else { thisCover.material.smooth = false; } //tween covers if(i == newIndex) { Tweener.addTween(thisCover, { x: 0, z: -180, rotationY: 0, time: .8, transition: "easeOutExpo", onUpdate: function():void{ needsRendered = true; } }); } else if(i < newIndex) { Tweener.addTween(thisCover, { x: (newIndex-i+1)*-planeSeparation-planeOffset, z: ((newIndex-i+1)*+planeSeparation)*.5, rotationY: -planeAngle, time: .8, transition: "easeOutExpo", onUpdate: function():void{ needsRendered = true; } }); } else { Tweener.addTween(thisCover, { x: ((i-newIndex+1)*planeSeparation)+planeOffset, z: ((newIndex-i+1)*-planeSeparation)*.5, rotationY: planeAngle, time: .8, transition: "easeOutExpo", onUpdate: function():void{ needsRendered = true; } }); } } currentIndex = newIndex; } else { thisCover = theCovers[newIndex].cover; //zoom in on selected cover if(!theCovers[newIndex].isZoomed){ Tweener.addTween(thisCover, { z: -390, time: 3, transition: "easeOutExpo", onUpdate: function():void{ needsRendered = true; } }); theCovers[newIndex].isZoomed = true; loadTrack(theCovers[newIndex].mp3); } else { Tweener.addTween(thisCover, { z: -180, time: 3, transition: "easeOutExpo", onUpdate: function():void{ needsRendered = true; } }); theCovers[newIndex].isZoomed = false; } } } } }