Papervision3D 2.0 + Go Tweening – Flipping Banner (Part 1)
Posted: December 10, 2007 at 11:01 pmSet up PapervisionTween to automatically render:
PapervisionTween.init(renderer, scene, camera, viewport);
Calling PapervisionTween to tween a plane:
var b:PapervisionTween = new PapervisionTween(_planeArray[0], {rotationY:0}, 0, 1, Quintic.easeInOut, onFlipDone); b.start();
I've also included the PapervisionTween code in the post in addition to the source files below, but let's move on the flipping code.
Here's the Core class that calls the Flip class:
package com.hydrotik.bannerflip3d { /** * @author Donovan Adams * @version December 10, 2007 * @description Papervision Page flip example * */ import flash.display.MovieClip; import flash.display.Sprite; import flash.display.Stage; import flash.events.MouseEvent; import flash.net.URLRequest; import flash.net.navigateToURL; import com.hydrotik.bannerflip3d.Flip; import com.hydrotik.bannerflip3d.FlipEvent; import com.hydrotik.utils.XMLLoader; import com.hydrotik.utils.XMLLoaderEvent; import flash.system.Capabilities; public class Core extends Sprite { private var _scope:MovieClip; private var _stage:Stage; private var _xml:XML; private var _url:String; private var _hit: Sprite; private var _targ : String; public function Core(scope:MovieClip, stage:Stage):void { _scope = scope; _stage = stage; var p:String; if (Capabilities.playerType == "External" || Capabilities.playerType == "StandAlone") { p = "../includes/admin/flippingbanner.xml"; } else { p = "/wp-content/flippingbanner2/includes/admin/flippingbanner.xml"; } var xml:XMLLoader = new XMLLoader(p); xml.addEventListener(XMLLoaderEvent.COMPLETE, onXMLComplete); xml.addEventListener(XMLLoaderEvent.ERROR, onXMLError); } private function onXMLError(event : XMLLoaderEvent) : void { trace(event); } // --== Private Methods ==-- private function onXMLComplete(event:XMLLoaderEvent):void { trace(":: onXMLComplete:"); _xml = event.xml; var _oFlip:Flip = new Flip(_scope, _stage, this, event.xml.banner.children(), "", new int(_xml.attribute("seconds"))); _oFlip.addEventListener(FlipEvent.COMPLETE, onCompleteHandler); _oFlip.addEventListener(FlipEvent.ON_FLIP, onFlipHandler); _hit = new Sprite(); _hit.graphics.beginFill(0x660000, 0); _hit.graphics.drawRect(0, 0, _stage.stageWidth, _stage.stageHeight); _scope.addChild(_hit); _hit.addEventListener(MouseEvent.CLICK, onClickHandler); _hit.buttonMode = true; _hit.useHandCursor = true; _hit.mouseEnabled = true; } private function onClickHandler(event:MouseEvent):void { navigateToURL(new URLRequest(_url), _targ); } private function onCompleteHandler(event:FlipEvent):void { _url = event.link; _targ = event.targ; } private function onFlipHandler(event:FlipEvent):void { _url = event.link; _targ = event.targ; } } }
Here's the updated Flip class using the Go tweening engine:
package com.hydrotik.bannerflip3d { /** * @author Donovan Adams * @version December 9, 2007 * @usage Example:<code></code> * @description * @history * @sends * @todo * */ import flash.display.*; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.TimerEvent; import flash.utils.Timer; import flash.utils.setTimeout; import org.papervision3d.cameras.Camera3D; import org.papervision3d.core.proto.SceneObject3D; import org.papervision3d.events.FileLoadEvent; import org.papervision3d.materials.BitmapFileMaterial; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Plane; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.scenes.Scene3D; import org.papervision3d.view.Viewport3D; import com.hydrotik.go.PapervisionTween; import fl.motion.easing.*; import org.papervision3d.core.proto.MaterialObject3D; [Event(name="COMPLETE", type="com.hydrotik.bannerflip3d.FlipEvent")] [Event(name="ON_FLIP", type="com.hydrotik.bannerflip3d.FlipEvent")] public class Flip extends EventDispatcher { public static const VERBOSE:Boolean = true; private var _scope:Sprite; private var _stage:Stage; private var _oCore:*; private var _assetPath:String; private var _materialArray:Array; private var _planeArray:Array; private var _array:XMLList; private var _count:int = 0; private var _next:int; private var _prev:int; private var _loader:Sprite; private var _seconds:int; //New 2.0 Privates private var renderer:BasicRenderEngine; private var camera:Camera3D; private var viewport:Viewport3D; private var debug : Function; private var scene : Scene3D; private var white : MaterialObject3D; private var bg : Plane; public function Flip(scope:Sprite, stage:Stage, core:*, a:XMLList, assetPath:String = "../flashassets/", s:int = 10):void { debug = trace; stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; _scope = scope; _stage = stage; _oCore = core; _array = a; _assetPath = assetPath; _seconds = s; _materialArray = []; _planeArray = []; scene = new Scene3D(); renderer = new BasicRenderEngine(); camera = new Camera3D(); camera.z = -100; viewport = new Viewport3D(500,300,true); viewport.alpha = 0; _scope.addChild(viewport); white = new ColorMaterial(0xFFFFFF); setTimeout(addedToStage, 100); } private function addedToStage():void{ if(VERBOSE) debug("\n\n>> Flip.addedToStage(); - args: "+[]); _loader = new Sprite(); _loader.graphics.beginFill(0x000000); _loader.graphics.drawRect(0, 0, 1, 4); _scope.addChild(_loader); _loader.x = (_stage.stageWidth/2) - 50; _loader.y = (_stage.stageHeight/2) - 2; for (var i:int = 0; i < _array.length(); i++) { _materialArray[i] = new BitmapFileMaterial(_array[i].attribute('src')); _materialArray[i].oneSide = true; _materialArray[i].smooth = true; _materialArray[i].addEventListener(FileLoadEvent.LOAD_PROGRESS, onFileProgress); _materialArray[i].addEventListener(FileLoadEvent.LOAD_COMPLETE, onFileComplete); _planeArray[i] = new Plane( _materialArray[i], 300, 156, 6, 6); scene.addChild(_planeArray[i]); _planeArray[i].name = i.toString(); _planeArray[i].rotationY = -180; } // PapervisionTween is extending LinearGo. PapervisionTween is a custom extension using custom syntax, running on the Go system // The init function passes the rendering info so that PapervisionTween can take care of updating the renderer PapervisionTween.init(renderer, scene, camera, viewport); } private function onFileProgress(event:FileLoadEvent):void { if(VERBOSE) debug("\t percentage: "+Math.round((event.bytesLoaded/event.bytesTotal)*100) + "%"); var sec:Number = 100/_array.length(); _loader.width = ((_count * sec) + ((event.bytesLoaded/event.bytesTotal) * sec)); } private function onFileComplete(event:FileLoadEvent):void { if(VERBOSE) debug("complete!"); // _count++; if (_count == _array.length()) { onImageQueueCompleteHandler(); } } private function onImageQueueCompleteHandler():void { // PapervisionTween is extending LinearGo. PapervisionTween is a custom extension using custom syntax, running on the Go system var l:PapervisionTween = new PapervisionTween(_loader, {alpha:0}, 0, .2, Quintic.easeInOut, loaderFade); l.start(); // PapervisionTween is extending LinearGo. PapervisionTween is a custom extension using custom syntax, running on the Go system var b:PapervisionTween = new PapervisionTween(_planeArray[0], {rotationY:0}, 0, 1, Quintic.easeInOut, onFlipDone); b.start(); // PapervisionTween is extending LinearGo. PapervisionTween is a custom extension using custom syntax, running on the Go system var c:PapervisionTween = new PapervisionTween(camera, {z:-100}, 0, 1, Quintic.easeInOut, onFlipDone); c.start(); _next = 0; _count = -1; bg = new Plane(white,5120,2560,10,10); bg.y = -200; bg.z = 500; bg.pitch(0); scene.addChild(bg); dispatchEvent(new FlipEvent(FlipEvent.COMPLETE, _next, _array[0].attribute('link'), _array[0].attribute('target'))); var myTimer:Timer = new Timer(_seconds * 1000); myTimer.addEventListener(TimerEvent.TIMER, timerHandler); myTimer.start(); } private function flip(id:int):void { // PapervisionTween is extending LinearGo. PapervisionTween is a custom extension using custom syntax, running on the Go system var a:PapervisionTween = new PapervisionTween(_planeArray[_next], {rotationY:180}, 0, 1, Quintic.easeInOut, onOldFlipDone); a.start(); // Update Data _prev = _next; _next = (id == _array.length() - 1) ? 0 : id + 1; var url:String = _array[_next].attribute('link'); var targ:String = _array[_next].attribute('target'); trace(url, targ); dispatchEvent(new FlipEvent(FlipEvent.ON_FLIP, _next, url, targ)); // PapervisionTween is extending LinearGo. PapervisionTween is a custom extension using custom syntax, running on the Go system var b:PapervisionTween = new PapervisionTween(_planeArray[_next], {rotationY:0}, 0, 1, Quintic.easeInOut, onFlipDone); b.start(); // PapervisionTween is extending LinearGo. PapervisionTween is a custom extension using custom syntax, running on the Go system var c:PapervisionTween = new PapervisionTween(camera, {z:-350}, 0, .5, Quintic.easeIn, onCameraHalf); c.start(); } private function onCameraHalf(event:Event = null):void { viewport.alpha = 1; var c:PapervisionTween = new PapervisionTween(camera, {z:-100}, 0, .5, Quintic.easeOut); c.start(); } public function timerHandler(event:TimerEvent):void { if(VERBOSE) debug("timerHandler: " + event); _count = (_count == _array.length() - 1) ? 0 : _count + 1; flip(_count); } private function onFlipDone(event:Event = null):void { if(VERBOSE) debug("flip done!"); } private function loaderFade(event:Event = null):void { viewport.alpha = 1; _scope.removeChild(_loader); } private function onOldFlipDone(event:Event = null):void { if(VERBOSE) debug("old flip done!"); _planeArray[_prev].rotationY = -180; } } }
And if you are curious here is the PapervisionTween extension of Go:
/** * Copyright (c) 2007 Moses Gunesch, MosesSupposes.com - Donovan Adams, blog.hydrotik.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.hydrotik.go { import flash.display.DisplayObject; import org.fuseproject.go.items.LinearGo; import org.papervision3d.objects.DisplayObject3D; //import flash.geom.ColorTransform; //import flash.filters.BlurFilter; //import flash.geom.Point; /** * A basic example of how you could build a tween on LinearGo. */ public class PapervisionTween extends LinearGo { // -== Public Properties ==- public function get width() : Number { return _rotationY; } public function set width(value : Number) : void { if (_state == STOPPED) _rotationY = value; } public function get startWidth() : Number { return _startRotationY; } public function set startWidth(value : Number) : void { if (_state == STOPPED) _startRotationY = value; } public function get target() : DisplayObject { return _target; } public function set target(obj : DisplayObject) : void { if (_state == STOPPED) _target = obj; } // -== Protected Properties ==- protected var _target : *; protected var _rotationY : Number; private static var _viewport:*; private static var _camera:*; private static var _scene:*; private static var _renderer : *; private var _closure : Function; private var debug : Function; protected var _startRotationY : Number; protected var _changeRotationY : Number; protected var _startProps : Object = {}; protected var _changeProps : Object = {}; protected var _propsTo : Object = {}; public static function init(renderer:*, scene:*, camera:*, viewport:*):void{ _renderer = renderer; _scene = scene; _camera = camera; _viewport = viewport; } // -== Public Methods ==- public function PapervisionTween( target:* = null, propsTo:Object = null, delay:Number = NaN, duration:Number = NaN, easing:Function = null, closure:Function = null) { super(delay, duration, easing); debug = trace; _target = target; if(closure != null) addCallback(closure); for (var prop in propsTo) { switch (prop) { case "alpha": if(_target is DisplayObject){ _propsTo[prop] = (propsTo[prop] != undefined) ? propsTo[prop] : _target[prop]; } if(_target is DisplayObject3D){ if(propsTo[prop] != undefined){ _propsTo[prop] = propsTo[prop]; }else{ _target.extra[prop] = new Number(1); _propsTo[prop] = _target.extra[prop] = _target.extra[prop]; } } break; default: _propsTo[prop] = (propsTo[prop] != undefined) ? propsTo[prop] : _target[prop]; } } } override public function start( ) :Boolean { if (!_target) return false; var prop:String; for (prop in _propsTo) { switch (prop) { case "alpha": if(_target is DisplayObject){ _startProps[prop] = _target[prop]; } if(_target is DisplayObject3D){ trace("start: "+_target.extra[prop]); _startProps[prop] = _target.extra[prop]; } break; default: _startProps[prop] = _target[prop]; } } if (useRelative) { for (prop in _propsTo) { _changeProps[prop] = _propsTo[prop]; } } else { for (prop in _propsTo) { _changeProps[prop] = (_propsTo[prop] - _startProps[prop]); //_propsTo[prop]; } } return (super.start()); } //TODO add alpha tweening syntax when released in 2.0 update override protected function onUpdate(type:String) : void { for (var prop in _propsTo) { switch (prop) { case "alpha": if(_target is DisplayObject3D){ //var val:Number = super.correctValue(_startProps[prop] + _changeProps[prop] * _position); //_target.material.bitmap.colorTransform(_target.material.bitmap.rect, new ColorTransform(1, 1, 1, val, 0, 0, 0, 0)); //_target.extra[prop] = val; debug("Current version of Pv3D does not support alpha tweening"); } if(_target is DisplayObject) _target[prop] = super.correctValue(_startProps[prop] + _changeProps[prop] * _position); break; default: _target[prop] = super.correctValue(_startProps[prop] + _changeProps[prop] * _position); } } if(_target is DisplayObject3D) _renderer.renderScene(_scene,_camera,_viewport); } } }
I plan on adding effects as well as the alpha property when 2.0 is able to support that. Shadows, layer effects, and more still to come!
Papervision 2.0 Flipping Banner Source Part 1
The Discussion
see what everyone is saying
[...] dropshadows, glow and few additional useful things like volume, pan, text. Donovan also started PapervisionTween which gives you control on Papervision3d 2.0 properties (basic at the moment). I used Fuse with [...]
Thank you! This is exactly what I was looking for. GoASAP is the beans!
How can i use the ReflectionView class with this flipping banner? I tried to integrate but had no success yet!
Haven't used that class as of yet, but most likely this code would need to be updated to support the latest rev of PV3d. When I finally get this updated to CS4 with the new branch of Papervision, I'll take a stab at it.