Archive for the 'ActionScript' Category

AS4 Wish: Shorthand Eventing with Flows

One thing I love and hate about ActionScript 3 is the eventing model. I love the departure from AS2 type callbacks. And I love the way it allows me to have loosely coupled classes. Anyway, to rephrase and refrain from stating the obvious, I think eventing is awesome.

But after the AS3 honeymoon … … I resent the number of times a day I find myself typing out object.addEventListener(…,…) and then object.removeEventListener(…,…). I resent it even more when I know that the event shall only happen once, normally for some kind of COMPLETE event; thus making the first line of my handler always be IEventDispatcher(e.target).removeEventListener(e.type,…). It’s just too verbose, especially when it’s such a core feature of ActionScript.

Now, I’m not trying to crawl onto the recent AS3 is harder and takes longer bandwagon here. I’m ecstatic that AS2 is not longer a daily thing for me; I wouldn’t even go back to it for a pay-rise. But, I feel something could be added to AS3 to make eventing less verbose and less prone to things such as memory leaks.

What makes eventing so verbose? Well, for every event we want to subscribe to, we do:

1) Add Listener
object.addEventListener(”eventtype”, eventHandler);

2) Create a function to handle that event
private function eventHandler(e:Event):void {
trace(”hello world”)
}

3) Remove Listener
object.removeEventListener(”eventtype”, eventHandler);

The creation of a handler function per event group is something that especially rubs me the wrong way, but when working in an asynchronous language, what else can you do? I propose a new concept called a “Flow”. A Flow mimics the blocking nature of synchronous languages while keeping inline with the asynchronous environment of ActionScript.

To outline my proposal, I’m only going to give a commented example, but I hope from it you’ll be able to take away the key concepts. And I stress concepts! As this probably won’t be the best syntactic solution.

class FlickrPhotoGizmo extends EventDispatcher {

	// Note that this is a "flow" and not a function.
	// Flows seem to be able to "block" until a matching event type is dispatched
	// Flows work with existing AS3 code .. ie. imageLoader.addEventListener(Event.COMPLETE, ...)

	// A flow will always dispatch a "FlowEvent" of constant type on return.
	// Flows are a one time deal; no need to keep listeners around once completed.
	// Null returns shall be detailed in the "FlowEvent" for later inspection.
	// The "->" notation is our "syntax sugar" 

	public flow loadAndFilterImage(searchTerm:String):BitmapData {

		var imageLoader:FlickrLoader = new FlickrLoader();
		var imageFilter:ImageFilter = new ImageFilter()
		var resultBitmap:BitmapData;

		imageLoader.getMostPopular(searchTerm) -> {
			Event.COMPLETE  -> resultBitmap = imageLoader.bitmapData;
			Event.NO_MATCH  -> return null;
		}

		imageFilter.filter(resultBitmap) -> {
			Event.COMPLETE -> {
				resultBitmap = imageFilter.filteredBitmapData;
				imageFilter.fooClean()
			}
			Event.ERROR -> return null;
		}

		imageFilter.filter2(resultBitmap)
			-> Event.COMPLETE
				-> resultBitmap = imageFilter.filteredBitmapData;

		return resultBitmap;
	}

}

// wrapper app

funtion init():void {

	var gizmo:FlickrPhotoGizmo = new FlickrPhotoGizmo();

	// let's load an image with happy people, then filter it...
	// ... then give the result to the "imageReady" function
	// remember: this is a one time "FlowEvent" event that results from a "flow"

	gizmo.loadAndFilterImage("happy people") -> imageReady;

	addPermEventHandlers();

}

function imageReady(e:FlowEvent):void {

	// no need to call removeEventListener as this is a one time event

	var image:BitmapData = e.yield;

	if (image) {
		addChild(new Bitmap(image))
	} else {
		var errorEvent:Event =  e.nullEvent
		switch (errorEvent.type) {
			case Event.NO_MATCH: trace("no happy people found :(")
		}
	}

	removePermEventHandlers();

}

// maybe we want this new syntax for permanent listeners too .. note: "o"
// (i know "o" might be a bad pick .. but just go with it)

function addPermEventHandlers {
	o-> MouseEvent.UP -> mouseUpHandler
	stage o-> KeyboardEvent.UP -> keyPressHandler
}

// and because we have permeant listeners, we need to be able to remove them .. note: "<"

function removePermEventHandlers {
	o<- MouseEvent.UP -> mouseUpHandler
	stage o<- KeyboardEvent.UP -> keyPressHandler
}

function mouseUpHandler(e:MouseEvent):void {
	trace("we're still loading that image for you, just wait .. blame Flickr")
	if (false && "anotherExample") {
		// this is short hand for .. this o<- MouseEvent.UP -> mouseUpHandler
		// we're able to do it because we're aware of the context
		o<-e
	}
}

function keyPressHandler(e:KeyboardEvent):void {

}

Flash 10 ActionScript API Documentation

Here is the full ActionScript API documentation for the latest Flash Player 10 release.

Some pages of the documentation still need to be updated, such as Sprite not inheriting the “z” axis for example (which it should). The DisplayObject page is the best class to look at for all the new 3D APIs.

Apart from a few pages needing updates, you should be able to find all the new APIs. Enjoy!

http://thebackbutton.com/misc/f10api/

Working with Shaders/Filters in Flash 10

Disclaimer: Beta API, APIs may change. Article based on investigatory work via code introspection.

Update: “Hydra” is now known as “Pixel Bender”

Loading Hydra Filters

The Flash API encapsulates Hydra Filters as a flash.display::Shader instances. To create a Shader instance we need to inject the byte code from a compiled Hydra filter file into it. We can do this in two familiar ways.

1) Using ActionScript 3 meta tags to inject the byte code directly into our compiled SWF.

[Embed(source="HydraFilter.hbc", mimeType="application/octet-stream")]
var Filter:Class;

var shader:Shader = new Shader(new Filter());

2) With the use of the URLLoader class which brings all the benefits of runtime loading.

function loadFilter() {
        loader = new URLLoader();
        loader.dataFormat = URLLoaderDataFormat.BINARY;
        loader.addEventListener(Event.COMPLETE, loadCompleteHandler);
        loader.load(new URLRequest("HydraFilter.hbc"));
}

function loadCompleteHandler(event:Event):void {
        var shader:Shader = new Shader(loader.data);
}

Accessing Filter Properties and Defining Input

Hydra filters usually take different parameters in order to control their output. For example, the existing BlurFilter in Flash has blurX and blurY to control the strength of its “blurring”. Flash 10 encapsulates a single filter parameter into a dynamic flash.display::ShaderParameter class instance. This class is dynamic in order for it to be able to inspect custom parameter meta-data . For example you might have minValue / maxValue set on the filter parameter (see below).

parameter float strength
 <
     description: "The strength of the blur";
     minValue: 0.0;
     maxValue: 50.0;
 >;

To set the value of a ShaderParameter, you can access the ‘value’ property of ShaderParameter and get/set Arrays on it. The size and type of data in the array all depends on the type of data the filter parameter is expecting. You can ask the ShaderParameter which flavor of Array it’s expecting by calling the ‘type’ property of ShaderParameter. In our Hydra code above you can see that the parameter is a float. A float requires a single Array element with the data type of that element being a Number. So for example, we could set … value = [10] .. and now the value of the strength is 10.

All of these ShaderParameter’s are wrapped up in another shader centric class called flash.display::ShaderData. This class is completely dynamic and gives access to ShaderParameter’s by their name. You should also be able to enumerate over them using a “for each” or “for in” loop. ShaderData also gives you assess to meta-data from the header of the Hydra filter such as its name, version, etc. So extending on the previous example, we can now say .. shaderData.strength.value = [10]

ShaderData also exposes the image input properties of a Hydra filter. For example our Hydra filter may be expecting a bitmap with an alpha channel …

input image4 src;

We represent this bitmap data input with yet another shader centric dynamic class called flash.display::ShaderInput. This class exposes some key meta-data type information about the input image property such as how many channels the bitmap should process (shaderInput.channels:int) and the index order of the property within the filter (shaderInput.index:int). The main property of this class is the ‘input’ property. Here we can set either a BitmapData, ByteArray or a Vector.<Number> instance that contains our input image. If the input is not a BitmapData type, then ‘width’ and ‘height’ properties must also be assigned to the ShaderInput instance.

Below is an example of assigning BitmapData to a ShaderInput (input image4 src) through our ShaderData:

shaderData.src.input = new BitmapData(123, 321, true, 0xFFCC00CC);

ActionScript developers should not typically need to create ShaderParameter and ShaderInput instances. All instances are created automatically to map to the requirements of the custom Hydra filter. All of these data instances should be accessible via the flash.display::Shader instance that we created before from our Hydra filter byte code. The property of Shader that gives us access to all of these parameters, inputs and meta-data is the ‘data’ property.

Example:

var shader:Shader = new Shader(hydraShaderByteCode);

trace(shader.data.name) // "DemoFilter"
trace(shader.data.version) // "1"
trace(shader.data.strength.maxValue) // 50.0
trace(shader.data.strength.description) // "The strength of the blur"
trace(shader.data.src.channels) // 4

shader.data.strength.value = [10]
shader.data.src.input =  new BitmapData(123, 321, true, 0xFFCC00CC);

Filter Rendering - BitmapFilter

Once you have encapsulated your hydra filter as a Shader, everything else starts to become very familiar. We just have one more element to add. The missing element is the flash.filters::ShaderFilter class. This class extends flash.filters::BitmapFilter, which is the base class for all existing DisplayObject filters. And so, we can now utilize our Shaders in exact same way that we would traditionally work with existing built in filters such as BlurFilter.

NOTE: BitmapFilter will automatically set the first ShaderInput for you. The DisplayObject that the BitmapFilter is assigned to becomes the first image input. Additional image inputs shall need to be defined in the usual way.

In this example below, we can how we wrap the Shader up into a ShaderFilter and apply it to a Sprite.

[Embed(source="HydraFilter.hbc", mimeType="application/octet-stream")]
var MyFilter:Class;

var shader:Shader = new Shader(hydraShaderByteCode);
var filter:ShaderFilter = new new ShaderFilter(shader);
filter.data.strength.value = [10];

var sprite:Sprite = new Sprite();
sprite.graphics.beginFill(0xcc00cc);
sprite.graphics.drawRect(0,0,123,321);
sprite.filters = [filter];

addChild(sprite);

Filter Rendering - Threaded Background Jobs

Sometimes a Hydra filter might take longer than desired to render. And because Flash currently runs on a single threaded rendering loop, a taxing filter could leave an applications UI unresponsive for an undesired amount of time. To avoid this scenario, Adobe have added the ability to perform background GPU filter rendering outside of the main thread, in the form of “jobs”.

The Flash API defines the flash.display::ShaderJob class for developers to manage this background rendering process. Here is an example using a BitmapData object as our output “bucket”.

function startJob(shader:Shader, target:BitmapData) {
        var job:ShaderJob = ShaderJob(shader, target);
        job.addEventListener(ShaderEvent.COMPLETE, shaderJobCompleteHandler)
        job.start()
}

function shaderJobCompleteHandler(e:ShaderEvent):void {
        var  result:BitmapData = e.bitmapData;
}

new Vector - ActionScript 3’s Typed Array

Flash Player 10 introduces a new core data type to store lists of data called “Vector”. It’s almost identical to the vanilla ActionScript array we use today but with the added benefit of being strictly/strongly typed. Strict typing is very beneficial, it helps create error free code while coding and compiling, allows for understandable APIs and best of all, increases code execution performance.

Vector is a top-level class just as Array is so you will not need to import it.

Below is an example of creating a Vector for the int type.

 var vec:Vector.<int> = new Vector.<int>();

Notice that we define the type of Vector with the use of the less-than/lower-than brackets.

Here is an extended example using a Vector for holding Sprites.

class Foo  {

	private var _displayChildren:Vector.<Sprite>;

	function Foo() {
		_displayChildren = new Vector.<Sprite>;
	}

	public function addChild(child:Sprite):void {
		_displayChildren.push(child);
	}

	public function removeChild(child:Sprite):void {
		var idx:int = _displayChildren.indexOf(child);
		_displayChildren.splice(idx,1);
	}

	public function get numChildren():uint {
		return _displayChildren.length;
	}

}

If you attempt to add data of the wrong type to a vector, you shall receive a “Type Coercion failed: cannot convert” error. There is however some exceptions, for example if you have a int typed Vector and you try to add a String to it using a push or unshift method, it shall perform an int(string) conversion.

intVec.push("00123")
intVec.push("hello")
trace(intVec) // 123, 0

If you try this however .. intVec[0] = “00123″ .. it shall result in a “Implicit coercion of a value of type String to an unrelated type int” error.

The only method Vector didn’t pick up from its Array cousin is sortOn. Apart from that, every method from Array is available to use to manipulate Vector.

Vector does introduce something new though, the ability to force a fixed collection length. Below is an example on how to enable fixed length.

// int Vector with fixed length of 5
var vec:Vector.<int> = new Vector.<int>(5, true);
trace(vec.fixed) // true
trace(vec) // 0, 0, 0, 0, 0

While in fixed mode, the methods push/pop/shift/unshift/splice/..etc shall not work and shall result in a “Cannot change the length of a fixed Vector.” error.

If you go out of the fixed range using the square bracket notation .. vec[15] = 1 .. you shall find this error “The index 15 is out of range 5.”.

Flash Player 10 Beta Released To The Public

Today, Adobe have released their first public beta of Flash Player 10 on their labs website. Code named “Astro”, Flash Player 10 introduces a whole fist full of compelling new features. It’s headline feature being a new range GPU utilization’s; from accelerated compositing to custom filter rendering. 3D is also introduced and bumped up to a first classes citizen with the introduction of the Z axis to all display object. On the coding side, we see the welcomed introduction of typed arrays which mean iterating over data just go a whole lot faster. Add in a new text layout engine and we’re only just touching the surface!

Player 10 is indeed an sneak peak into the future of Flash. If they can do this much with just one version release, just imagine what is going to happen in 11 and 12. Dynamic VM scripting languages FTW! :)

Why are you still reading this? Check it out: labs.adobe.com

removeEventListener causing memory leak?

Update

After inspecting my dispatcher .. i find this awful mistake:

override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0.0, useWeakReference:Boolean=false):void {
_node.addEventListener(type, listener, useCapture, priority, useWeakReference)
}

override public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void {
_node.addEventListener(type, listener, useCapture)
}

(DOH!!!!!!!!!! LOL)

——

To cut to the chase, in my personal AS3 framework, I’ve implemented deconstructors in all my DisplayObjects objects. The deconstructors mostly feature removeEventListener calls as I try to stay away from using weak refs. Today, while making a regular memory leak check using Flex Builder 3’s profiler, I noticed that I had a few DisplayObjects still latched onto an event dispatcher model object they were supposed to have let go of.

The first thing I did was to put a trace() in my deconstructor to make sure it was being called, yes it was. WTF? After some more digging, I then saw that this particular DisplayObject was flagged to not attach itself to the event dispatcher in the first place. (Wait, you mean that addEventListener hadn’t even been called in the first place? Yes!) So I switched the flag so that the DisplayObject would attach to the event dispatching model and guess what, this time it got GC’d after the deconstructor call.

So why is removeEventListener causing this to happen, the API docs define the method as:

“Removes a listener from the EventDispatcher object. If there is no matching listener registered with the EventDispatcher object, a call to this method has no effect.”

Has no effect, huh? But it seems to be doing something. Has anyone noticed anything similar to this?

Thoughts about Hydra in Flash 10

One of the things I’m looking forward to in Flash Player 10 is support for custom bitmap filters created using Hydra. If you’re not up to speed with Hydra, then all you need to know is that it’s a language that lets you define a custom filter to apply to display list objects in Flash much like the filters you see into todays Flash Player. Great huh? Well it gets even better. The new hydra filters are able to produce their results by utilizing the users graphics card, thus taking a huge amount of stress off the CPU and thus upping overall performance immensely.

Hydra is by no means is breaking news in the Flash world but, I just want to share two thoughts on why I’m excited. It’s able to produce some truly awesome bitmap filters. Your imagination (and coding skill) is your only limitation, but for me, the number one reason why Hydra will kick ass is faster alpha tweening! Alpha adjustment is probably the simplest bitmap filter in existence and the one that’s most commonly used in Flash projects today. This alone is enough reason to be excited about Hydra.

My second reason is to do with 3D rendering using bitmap filters. A few months ago I came across a blog post by Paul Ortchanian. In this post he had jumped on to the “me too” Flash cover-flow band wagon but, Paul’s approach is quite different to many clones before it. Instead of relying on a Papervision type 3D engine or applying simple matrix skews, Paul has gone down another route.

Paul decided on using a built in bitmap filter that is currently available in todays Flash Player called, Displacement Map Filter, to skew and size his album art. His online example looks to animate very smoothly and this is without the use of Hydra and the graphics card. Now, just imagine this cover-flow example utilizing a Hydra filter and I think you’ll understand Hydra’s 3D possibilities. Just think what Papervision3D would be like running on the GPU! It’s all very possible, especially now that PV3D-2 has a plugable rendering engine.

Flash Player 10 can’t come soon enough! :)

Does anybody want ‘Anchor Sprite’ to be Released?

A couple of weeks ago I created a small video demo of a project of mine code named “Anchor Sprite”. It is a small ActionScript 3 library to manage layout and constraints of display objects within a pure AS3 project.

View Original Post

The original post received no comments so I assumed no body is interested or the video wasn’t working or people just didn’t get it. So I want to now implicitly ask if anyone would like me to release this library?

MaterialManager memory leak in Papervision3d: Great White

I’ve just starting using Papervision3d for the first time and I decided to go head first into the Great White build.

After completing a portion of work in my project I usually run the profiler to make sure objects are being collected. So, after finishing my Papervision3d portion of work, I ran the project in the profiler. I immediately noticed that I had a worry number of PV3D objects still hanging out, taking up a lot of memory. They we’re mainly math type objects such as Number3D and Matrix3D. And after exploring some more using the profiler, I was able to see that the culprit was the MaterialManager. And surprise , surprise, it’s a Singleton.

Now, I’m not one of those people who hate Singleton’s in projects, all I ask is that they keep themselves tidy. So that when a singleton is “idle”, it’s memory foot print is minimal. And yes I understand that “Great White” is in a pre-release status so I’m not on a rant and bitch session here. I would merely like to warm others who are using Great White for projects to be carful.

So, how does MaterialManager leak? It would seem that the following Dictionary just keeps growing and growing with complex Material objects.

private var materials:Dictionary;

And in the way I’m using Papervision3d; I end up with hundreds of bitmap BitmapMaterial’s and WireframeMaterial’s by having Cubes covered in the BitmapMaterial’s fly on to stage and then off again. Once I remove the Cube from the Scene3D, I expected the Material to be GC’ed because I saw no hard deconstruct method. But no, I saw this Dictionary becomes quite large, very quickly.

To work around this problem I temporally commented out the body of the registerMaterial method so that my Material would never be added to materials:Dictionary.

public static function registerMaterial(material:MaterialObject3D):void {
//getInstance()._registerMaterial(material);
}

But you may need to build your own work around if you’re using shaders as the MaterialManager seems to be connected to ShadedMaterial’s. Maybe you could call init() on MaterialManager once you’re finished with your papervision3d portion of the project. Or work closely with MaterialManager when removing objects from the Scene3D.

I’m sure this issue shall be corrected for the final release of PV3D 2 but until then this work around will be working for me.

ActionScript 3 Layout & Constraints - Video Demo

Around the middle of December I decided to see if I could improve my ActionScript 3 life a little by creating a very basic layout and constraints framework. I thought it would be the perfect project to help speed up my overall development times.

Starting off, I didn’t plan the framework at all, I just kept coding until I got to the end result which, is usually the way things work for me. And after the couple of tinkering around down days, I ended up with a decorator pattern that I could apply to any existing DisplayObject.

This means that you don’t have to apply this framework to the whole application. The stage can stay as a Sprite; your existing components will still display where you told them to display. This framework can be added to any existing project without the need to upgrading anything and without the fear breaking anything which, I think is the best thing about it.

Unfortunately, I shall not be releasing the framework today. I feel that I can still improve upon it and clean the API a little. But I am attaching a video “walk through” of the API and a link to the code I use in the video.

Disclaimers:

  • This is my first ever video! - be nice
  • It’s unedited and done in a single take .. eeek!
  • I tell a tiny lie close to the end about an offset being a pixel value when it was in-fact it’s a percentage .. doh!
  • The Quicktime movie isn’t hinted for streaming .. sorry

View Code - Click Here

Link to Video (for if you can’t see the embed)

If you have any feedback or questions please feel free to leave a comment.

Also, if you are living in the Bay Area .. please remember that the first San Flashcisco user group meeting is on Thursday (Jan 17th 08). For more information, please visit SanFlashcisco.com

Next Page »