AS3 Tweening + Go + HydroTween rev 0.3.1
Here’s my latest tweening module for Go called HydroTween. Using HydroTween with the Go system is as easy as:
Be sure to go to goasap.org to get the Go source.
HydroTween Source
Thursday, December 20th, 2007
Here’s my latest tweening module for Go called HydroTween. Using HydroTween with the Go system is as easy as:
Be sure to go to goasap.org to get the Go source.
Thursday, December 20th, 2007
I discovered a few things when trying to add img tags to html content on a site I have been working on. Mabye this is common knowledge, but I thought I’d share my experience since I had a hard time getting anymore info on it.
Basically I wanted to link the embedded images in my TextField so the popup a larger version of the image. Simple enough, yet when I wrapped the img tag with an href, the outside of the image would show the hand cursor, but the image wouldn’t link. Now if the parent of the img is the TextField, then wouldn’t it make sense to have numChildren as a TextField Method? Then I could loop through the children of the text field and create buttons. I’ve made this request to Adobe, and so far they have been receptive to the idea. Hopefully this will get passed through.
I did however, come up with another way to dynamically load images into a TextField. When loading a swf into a TextField using the img tag you can set the instance name of that swf using the id attribute. I use this id attribute to pass the path to the image, as well as an image id that is passed into the popup window that loads the larger image. Here’s an example of the html source that is passed into the TextField.
I separate the two parameters using a comma which are String split in the thumb.swf. Here’s the code in the thumb.swf:
var image:Sprite = new Sprite();
image.useHandCursor = image.buttonMode = image.mouseEnabled = true;
image.addEventListener(MouseEvent.CLICK, onClick);
this.addChild(image);
var loader:Loader = new Loader();
var request:URLRequest = new URLRequest(imagepath);
loader.load(request);
image.addChild(loader);
var border:Sprite = new Sprite();
this.addChild(border);
border.graphics.lineStyle(2, 0xCC3300, 1, true, “none”);
border.graphics.drawRect(1,1,148, 148);
function onClick(event:MouseEvent):void{
navigateToURL(new URLRequest(“javascript:window.open(’image.php?cat=slideshow&id=”+link+“‘,’atest’,'menubar=yes,resizable=no,width=710,height=730,left=50,top=50′);”), “_self”);
}
Wednesday, December 19th, 2007
Turns out when I modify the wiki, the revision number jumps since the wiki is considered a commit. Makes sense since you can edit the wiki locally and upload to the server.
Updates:
Modified the FLV loading so it doesn’t use the Playback component source. It does simple streaming, event.file returns the NetStream Object. No more issues of having to link, import, or embed the component code.
Also included is Jesse Graupmann’s suggestion and implementation of prioritizing and bundling of sub loaders. Basically it let’s you do this:
Currently it requires setting the MIME type manually, but soon it will be set up so that if QueueLoader is in the path, it will recognize it as well. More enhancements and examples of this feature to come.
Thursday, December 13th, 2007
Set up PapervisionTween to automatically render:
Calling PapervisionTween to tween a plane:
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:
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(0×660000, 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:
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(0×000000);
_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:
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!
Monday, December 10th, 2007
Sorry for the version jump. When I added flv and supporting files the SVN jumped up a few numbers. Regardless I am going to stop posting examples directly here on the blog with the exception of updates and new features worth noting. I think it’s also an easy way for people to communicate questions, comments, concerns, etc. As far as usage, downloads, etc., I think it will be easier for me to keep all the necessary info on the google project site then retroactively updating my previous posts.
Important Updates
QUEUE_INIT and ITEM_INIT have been changed to reflect the internal structure. They are now QUEUE_COMPLETE and ITEM_COMPLETE. Sorry if this causes confusion but it needed to be changed at some point.
FLV support has been added finally. The event.file var in the callback will return a VideoPlayer Object for video control.
I did some other utilitarian and formatting tasks event meta info, debugging organization with parent level accessibility, etc.
Click here for the current rev
Monday, December 10th, 2007
Latest Version Info:
Click here for the current rev
Click here for the usage guide
Also click here for any posts related to the latest changes:
QueueLoader Updates
Wednesday, December 5th, 2007
Latest Version Info:
Click here for the current rev
Click here for the usage guide
Also click here for any posts related to the latest changes:
QueueLoader Updates
Here are some different ways to use QueueLoader.
Basic Loading
var _oLoader:QueueLoader = new QueueLoader();
var img = new Sprite();
addChild(img);
_oLoader.addItem(“images/image1.jpg”), img, {title:“Image “});
_oLoader.execute();
Load Monitoring
var _oLoader:QueueLoader = new QueueLoader();
var img1 = new Sprite();
addChild(img1);
_oLoader.addItem(“images/image1.jpg”), img1, {title:“Image 1″});
var img2 = new Sprite();
addChild(img2);
_oLoader.addItem(“images/image2.jpg”), img2, {title:“Image 2″});
_oLoader.addEventListener(QueueLoaderEvent.QUEUE_START, onQueueStart, false, 0, true);
_oLoader.addEventListener(QueueLoaderEvent.ITEM_START, onItemStart, false, 0, true);
_oLoader.addEventListener(QueueLoaderEvent.ITEM_PROGRESS, onItemProgress, false, 0, true);
_oLoader.addEventListener(QueueLoaderEvent.ITEM_INIT, onItemInit,false, 0, true);
_oLoader.addEventListener(QueueLoaderEvent.ITEM_ERROR, onItemError,false, 0, true);
_oLoader.addEventListener(QueueLoaderEvent.QUEUE_PROGRESS, onQueueProgress, false, 0, true);
_oLoader.addEventListener(QueueLoaderEvent.QUEUE_INIT, onQueueInit,false, 0, true);
_oLoader.execute();
//Listener functions
function onQueueStart(event:QueueLoaderEvent):void {
trace(“>> “+event.type);
}
function onItemStart(event:QueueLoaderEvent):void {
trace(“\t>> “+event.type, “item title: “+event.title);
}
function onItemProgress(event:QueueLoaderEvent):void {
trace(“\t>> “+event.type+“: “+[” percentage: “+event.percentage]);
}
function onQueueProgress(event:QueueLoaderEvent):void {
trace(“\t>> “+event.type+“: “+[” queuepercentage: “+event.queuepercentage]);
}
function onItemInit(event:QueueLoaderEvent):void {
trace(“\n>>”+event.message+“\n“);
}
function onItemError(event:QueueLoaderEvent):void {
trace(“\n>>”+event.message+“\n“);
}
function onQueueInit(event:QueueLoaderEvent):void {
trace(“\n>>”+event.message+“\n“);
}
Manually specifying a MIME type
var _oLoader:QueueLoader = new QueueLoader();
var img = new Sprite();
addChild(img);
_oLoader.addItem(“images/image1.jpg”), img, {title:“Image “, mimeType:QueueLoader.FILE_IMAGE});
_oLoader.addEventListener(QueueLoaderEvent.QUEUE_INIT, onQueueInit,false, 0, true);
_oLoader.execute();
Loading XML
var _oLoader:QueueLoader = new QueueLoader();
var _xml:XML;
_oLoader.addItem(“includes/admin/test.xml”, null, {title:“XML”});
_oLoader.addEventListener(QueueLoaderEvent.ITEM_INIT, onItemInit,false, 0, true);
_oLoader.execute();
function onItemInit(event:QueueLoaderEvent):void {
trace(“\t>> XML: “+event.type, “item title: “+event.title);
if(event.filetype == QueueLoader.FILE_XML){
_xml = new XML(event.file);
}
}
Loading CSS
var _oLoader:QueueLoader = new QueueLoader();
var _css:StyleSheet = new StyleSheet();
_oLoader.addItem(“includes/admin/style.css”, null, {title:“CSS”});
_oLoader.addEventListener(QueueLoaderEvent.ITEM_INIT, onItemInit,false, 0, true);
_oLoader.execute();
function onItemInit(event:QueueLoaderEvent):void {
if(event.filetype == QueueLoader.FILE_CSS){
trace(“\t>> CSS: “+event.type, “item title: “+event.title);
_css.parseCSS(event.file);
}
}
Drawing the frames of an external SWF to Bitmap Objects in an Array
var externalImageBitmapContainer:Bitmap = new Bitmap();
addChild(externalImageBitmapContainer);
var externalImageContainer:Sprite = new Sprite();
addChild(externalImageContainer);
var _oLoader:QueueLoader = new QueueLoader();
_oLoader.addItem(“flashassets/swf/externalimages.swf”, externalImageContainer, {title:“externalimages”, drawFrames:true});
_oLoader.addEventListener(QueueLoaderEvent.QUEUE_INIT, onQueueInit,false, 0, true);
_oLoader.execute();
function onQueueInit(event:QueueLoaderEvent):void {
trace(“** “+event.type);
// This passes a Bitmap object of the 2nd frame
// in the external swfstored in bmArray
externalImageBitmapContainer.bitmapData = event.bmArray[1];
}
Accessing Class references in an externally loaded SWF
var addedDefinitions:LoaderContext = new LoaderContext();
addedDefinitions.applicationDomain = ApplicationDomain.currentDomain;
var _oLoader:QueueLoader = new QueueLoader(false, addedDefinitions, true);
var soundSWF = new MovieClip();
soundSWF.name = “externalSounds”;
addChild(soundSWF);
var soundChannel:SoundChannel = new SoundChannel();
_oLoader.addItem(prefix(“”) + “flashassets/swf/externalsounds.swf”, soundSWF, {title:“sounds”, drawSWF:false, mimeType:QueueLoader.FILE_SWF});
_oLoader.addEventListener(QueueLoaderEvent.QUEUE_INIT, onQueueInit,false, 0, true);
_oLoader.execute();
function onQueueInit(event:QueueLoaderEvent):