topical media & game development

talk show tell print

lib-flex-cover-com-dougmccune-containers-CoverFlowContainer.ax

lib-flex-cover-com-dougmccune-containers-CoverFlowContainer.ax (swf ) [ flash ] flex


  package com.dougmccune.containers
  {
          import caurina.transitions.Tweener;
          
          import flash.display.DisplayObject;
          import flash.geom.ColorTransform;
          
          import mx.core.EdgeMetrics;
          
          import org.papervision3d.objects.DisplayObject3D;
          
          public class @ax-lib-flex-cover-com-dougmccune-containers-CoverFlowContainer extends BasePV3DContainer
          {
                  
The angle that each Plane is rotated on the y axis. This corresponds to PaperVision's yRotation property on the Plane. This is in degrees and should range from 0-90. A value of 0 means no rotation is applied and a value of 90 would mean the Plane is rotated so much that it would effectively disappear.

  
                  public var rotationAngle:Number = 70;
                  
                  
If true the Planes near the edge of the component will fade to transparent. Kind of a cool effect sometimes if you want it.

  
                  public var fadeEdges:Boolean = false;
                  
                  
@private For some of the layout stuff we need to know the max height of all the children. As children are added we make sure to update maxChildHeight.

  
                  protected var maxChildHeight:Number;
                  
                  
@private For some of the layout stuff we need to know the max width of all the children. As children are added we make sure to update maxChildWidth.

  
                  protected var maxChildWidth:Number;
                  
                  override public function addChild(child:DisplayObject):DisplayObject {
                          super.addChild(child);
                          
                          if(isNaN(maxChildHeight) || child.height > maxChildHeight) {
                                  maxChildHeight = child.height;
                          }
                          
                          return child;
                  }
                  
                  override protected function layoutChildren(unscaledWidth:Number, unscaledHeight:Number):void {
                          super.layoutChildren(unscaledWidth, unscaledHeight);
                          
                          layoutCoverflow(unscaledWidth, unscaledHeight);
                  }
                          
                  protected function layoutCoverflow(uncaledWidth:Number, unscaledHeight:Number):void {
                                  
                          var n:int = numChildren;
                          
                          for(var i:int=0; i<n; i++) {
                                  var child:DisplayObject = getChildAt(i);
                                  var plane:DisplayObject3D = lookupPlane(child);
                                  plane.container.visible = true;
                                  
                                  var abs:Number = Math.abs(selectedIndex - i);
                                  
                                  var horizontalGap:Number = getStyle("horizontalSpacing");
                                  if(isNaN(horizontalGap)) {
                                          //this seems to work fairly well as a default
                                          horizontalGap = maxChildHeight/3;
                                  }
                                  
                                  var verticalGap:Number = getStyle("verticalSpacing");
                                  if(isNaN(verticalGap)) {
                                          verticalGap = 10;
                                  }
                                  
                                  var xPosition:Number = selectedChild.width + ((abs-1) * horizontalGap);
                                  var yPosition:Number = -(maxChildHeight - child.height)/2;
                                  var zPosition:Number = camera.z/2 + selectedChild.width + abs * verticalGap;
                                  
                                  var yRotation:Number = rotationAngle;
                                  
                                  //some kinda fuzzy math here, I dunno, I was just playing with values
                                  //note that this only gets used if fadeEdges is true below
                                  var alpha:Number = (unscaledWidth/2 - xPosition) / (unscaledWidth/2);
                                  alpha  = Math.max(Math.min(alpha*2, 1), 0);
                                  
                                  if(i < selectedIndex) {
                                          xPosition *= -1;
                                          yRotation *= -1;
                                  }
                                  else if(i==selectedIndex) {
                                          xPosition = 0;
                                          zPosition = camera.z/2;
                                          yRotation = 0;
                                          alpha = 1;
                                  }
                                  
                                  if(fadeEdges) {
                                          //here's something sneaky. PV3D applies the colorTransform of the source movie clip to the
                                          //bitmapData that's created. So if we adjust the colorTransform that will be shown in the
                                          //3D plane as well. Cool, huh?
                                          var colorTransform:ColorTransform  = child.transform.colorTransform;
                                          colorTransform.alphaMultiplier = alpha;
                                          child.transform.colorTransform = colorTransform;
                                          plane.material.updateBitmap();
                                  }
                                  
                                  if(reflectionEnabled) {
                                          var reflection:DisplayObject3D = lookupReflection(child);
                                          
                                          if(fadeEdges) {
                                                  reflection.material.updateBitmap();
                                          }
                                          
                                          //drop the reflection down below the plane and put in a gap of 2 pixels. Why 2 pixels? I think it looks nice.
                                          reflection.y = yPosition - child.height - 2;
                                          
                                          if(i!=selectedIndex) {
                                                  Tweener.addTween(reflection, {z:zPosition, time:tweenDuration/3});
                                                  Tweener.addTween(reflection, {x:xPosition, rotationY:yRotation, time:tweenDuration});
                                          }
                                          else {
                                                  Tweener.addTween(reflection, {x:xPosition, z:zPosition, rotationY:yRotation, time:tweenDuration});
                                          }
                                  }
                                  
                                  if(i!=selectedIndex) {
                                          Tweener.addTween(plane, {z:zPosition, time:tweenDuration/3});
                                          Tweener.addTween(plane, {x:xPosition, y:yPosition, rotationY:yRotation, time:tweenDuration});
                                  }
                                  else {
                                          Tweener.addTween(plane, {x:xPosition, y:yPosition, z:zPosition, rotationY:yRotation, time:tweenDuration});
                                  }
                                  
                                  if(i == selectedIndex) {
                                          var bm:EdgeMetrics = borderMetrics;
                  
                                          //We need to adjust the location of the selected child so
                                          //it exactly lines up with where our 3D plane will be. 
                                          child.x = unscaledWidth/2 - child.width/2 - bm.top;
                                          child.y = unscaledHeight/2 - child.height/2 - yPosition - bm.left;
                                          
                                          //the normal ViewStack sets the visibility of the selectedChild. That's no good for us,
                                          //so we just reset it back. 
                                          child.visible = false;
                                  }
                          }
                  }
          }
  }


(C) Æliens 18/6/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.