Flex Effects with Pixel Bender filters, part 1.

This is the first of a two part series on using Pixel Bender filters in Flex effects. I've recently started to spend a bit of time with Pixel Bender and have found it to be a good tool for creating interesting effects and transitions in Flex. Even if you don't write any yourself, there are plenty available to use at the Pixel Bender Exchange

In this first part I'll cover an example of making an Effect and EffectInstance that extend the Flex framework and also use a Pixel Bender filter to achieve the effect. In the second part I'll cover writing a Pixel Bender filter to use with a custom effect.

I won't go over embedding and instantiating a filter as a Shader; this is well documented here. There is also a good example of animating a Pixel Bender filter here.

The Pixel Bender filter I'm going to use for this example is a dissolve effect from the BlackBookSafe sample project on Adobe Developer Connection. This filter creates a patterned dissolve effect that can be manipulated via one parameter, 'transition', which goes from 1, invisible, to 0, completely normal. Values in between giving the dissolve effect.

To turn this into an effect I have made two new classes that extend TweenEffect and TweenEffectInstance. Doing this means I take advantage of all the Flex effects functionality, and get to use the effect as a simple MXML component. The first new class, DissolveEffect, is very simple. It has two properties which it will pass onto effect instances and overrides two methods: getAffectedProperties() and initInstance(). Scroll to the bottom to see this class in its entirety.

The second class is DissolveInstance (not to be confused with mx.effects.effectClasses.DissolveInstance). This class has the Pixel Bender filter (the pbj file) embedded into it, as well as a Shader and ShaderFilter. Beyond this it is much like the FadeInstance class in that it does a small amount of validation on its properties and then uses its superclass' tween to create the desired effect. In this case the tween's value updates the transition value on the Pixel Bender filter (or more precisely the transition.value[0]), and updates the target's filters on each tween update.

 
public class DissolveEffect extends TweenEffect 
{ 
    private static var AFFECTED_PROPERTIES:Array = [ "filters" ];
 
    [Inspectable(category="General", defaultValue="undefined")] 
    public var transitionFrom:Number; 
 
    [Inspectable(category="General", defaultValue="undefined")] 
    public var transitionTo:Number; 
 
    public function DissolveEffect(target:Object=null) 
    { 
        super(target); 		 	instanceClass = DissolveInstance; 
    } 


    override public function getAffectedProperties():Array 
    { 
        return AFFECTED_PROPERTIES; 
    } 


    override protected function initInstance(instance:IEffectInstance):void 
    { 
        super.initInstance(instance); 
        var dissolveInstance:DissolveInstance = DissolveInstance(instance);
        dissolveInstance.transitionFrom = transitionFrom; 
        dissolveInstance.transitionTo = transitionTo; 
    } 
} 

 
public class DissolveInstance extends TweenEffectInstance 	
{ 
 
    [Embed(source="assets/disolve.pbj", mimeType="application/octet-stream")] 
    private var dissolveKernel:Class; 
 
    private var dissolveShader:Shader; 
    private var shaderFilter:ShaderFilter; 
 
    public var transitionFrom:Number; 
    public var transitionTo:Number; 
 
    public function DissolveInstance(target:Object) 
    { 
        super(target); 
        dissolveShader = new Shader( new dissolveKernel() ); 
        shaderFilter = new ShaderFilter( dissolveShader ); 
    } 
 
    override public function initEffect(event:Event):void 
    { 
        super.initEffect(event); 
 
        switch (event.type) 
        {	
            case "childrenCreationComplete": 
            case FlexEvent.CREATION_COMPLETE: 
            case FlexEvent.SHOW: 
            case Event.ADDED: 
            { 
                if (isNaN(transitionFrom)) 
                    transitionFrom = 1; 
                
                if (isNaN(transitionTo)) 
                    transitionTo = 0; 


                break;
            } 
            case FlexEvent.HIDE: 
            case Event.REMOVED: 
            { 
                if (isNaN(transitionFrom))
                    transitionFrom = 0; 
 
                if (isNaN(transitionTo)) 
                    transitionTo = 1; 
                break; 
            } 
        } 
    } 
 
    override public function play():void 
    { 
        super.play(); 
 
        var values:PropertyChanges = propertyChanges; 
 
        if (isNaN(transitionFrom) && isNaN(transitionTo)) 
        {	
            if (values && values.end["transition"] !== undefined) 
            { 
                transitionFrom = 1; 
                transitionTo = values.end["transition"]; 
            } 
            else 
            { 
                transitionFrom = 1; 
                transitionTo = 0; 
            } 
        } 
        else if (isNaN(transitionFrom)) 
        { 
            transitionFrom = (transitionTo == 0) ? 1 : 0; 
        } 
        else if (isNaN(transitionTo)) 
        { 
            if (values && values.end["transition"] !== undefined) 
            { 
                transitionTo = values.end["transition"]; 
            } 
            else
            { 
                transitionTo = (transitionFrom == 0) ? 1 : 0;
            } 
        }	
 
        tween = createTween(this, transitionFrom, transitionTo, duration);
        dissolveShader.data.transition.value[0] = transitionFrom;
 
        if(target.filters) 
        { 
            setTargetFilters( false, true ); 
        } 
        else 
            target.filters = [ shaderFilter ]; 
    }


    override public function onTweenUpdate(value:Object):void 
    { 
        dissolveShader.data.transition.value[0] = value; 
        setTargetFilters( true, true ); 
    } 
 
    override public function onTweenEnd(value:Object):void 
    { 
        super.onTweenEnd(value);	
        setTargetFilters( true, false ); 
    }


    private function setTargetFilters( splice:Boolean, push:Boolean ):void 
    { 
        var arr:Array = target.filters; 
        if( splice ) 
            arr.splice( target.filters.indexOf( shaderFilter ), 1 ); 
 
        if( push ) 
            arr.push( shaderFilter ); 	target.filters = arr; 
    } 
} 

Dynamically resizing AIR windows with non-resizing content.

Following on from my previous post concerning dyncamically resizing AIR windows with user resize (based on Daniel Wabyick’s example here), I wanted to cover a further modification I made; that of having the window resize dynamically, but the content stay the same.

To be more specific, I wanted a content area to remain a fixed size when the window resized dynamically, but maintain a percentage width of the area when the window was resized by the user. (If that makes no sense, download the example after the jump.)

There are two main additions made to the previous example to achieve this. Firstly was to fix the width of the non-resizing area at the start of the resize effect. This was done by adding effectStart="{mainHBox.width=mainHBox.width}" to the Resize effect.

The second part is to return the area to a percent width when the user resizes the window, so the gripperDownHandler method becomes:

 
private function gripperDownHandler():void 
{ 
    //adds an extra bit of safety incase the mouseUp occures outside the gripper      
    stage.addEventListener( MouseEvent.MOUSE_UP, gripperUpHandler ); 
    
    chrome.setStyle("top", 10); 
    chrome.setStyle("bottom", 10); 
    chrome.setStyle("left", 10); 
    chrome.setStyle("right", 10); 
    chrome.setStyle("resizeEffect", null); 
 
    mainHBox.percentWidth = 
        (mainHBox.width / (chrome.width - (mainContent.getStyle("paddingLeft")  		+
        mainContent.getStyle("paddingRight") + mainContent.borderMetrics.left 		+
        mainContent.borderMetrics.right))) 		*100;


    nativeWindow.startResize(); 
} 

The resizeHandler code has also undergone a slight tweak. It now bases the reduction target size for the chrome on the width of mainHbox. This prevents rounding errors, which could create scrollbars or slowly enlarging margins on continued resizes.

Resize Flex Image correctly and add Bitmap smoothing

If you have ever used the Flex Image component, set its minWidth / minHeight or percentWidth / percentHeight you may have noticed some strange layout issues, and that the scaled quality is not that good. You can use 3rd party Image components to get round these issues, or this very simple load handler on the image. When using these properties, the Image component itself is NOT changed, rather the content within it. So it may appear to have scaled down, but the outer bounds of the Image component (not the bitmap within it) remain the original size.

Also, when scaling the Image component, bitmap smoothing is not enabled, and as it is private you cant do anything about it - so your scaled down image is a bit jagged. There are 3rd party Image components to get round these issues, or this very simple load handler on the image...

 
private function imageLoaded(event:Event):void 
{ 
    var img:Image = event.target as Image; 

    // re set the image source to a new Bitamp that is created from the current image 
    // bitmap data, but this time with smoothing enabled 	
    img.source = new Bitmap( Bitmap(img.content).bitmapData, "auto", true ); 

    // Set the scaling of the image to 20px 	
    img.scaleX = img.scaleY = (20 / img.contentHeight); 
} 

How to use custom bitwise flags in Actionscript

The Alert class in AS3 is a good example of using bitwise flags to specify a configuration without having to set lots of separate Boolean flags. Its also very easy to create bitflags for yourself, which save time, code and memory! Below is an example of custom bitflags as well as an explanation of how it all works. You can have various buttons enabled in the Flex Alert - “OK”, “NO”, “Cancel” etc. Any combination can be used, and the configuration is all set via one argument. Each value is separated with the bitwise OR operator (the pipe | – not to be confused with the logical OR operator || - two pipes).

The example below would contain OK, NO and CANCEL buttons.

 
Alert.show(“My Alert message”, “My Alert tittle”, Alert.OK | Alert.NO | Alert.CANCEL );
 

Below details how this works in terms of bitwise operations, but first here is an example of how to use this in your own program.

Example of using custom bitwise flags in actionscript Create a static class to hold the values and a method to test them.

 
package 
{ 
 
public class Colours 
 { 
 
    public static const ULTRA_RED:uint 		= 1; 
    public static const RED:uint 			= 2; 
    public static const ORANGE:uint 		= 4; 
    public static const YELLOW:uint 		= 8; 
    public static const GREEN:uint			= 16; 
    public static const BLUE:uint			= 32; 
    public static const INDIGO:uint 		= 64; 
    public static const VIOLETE:uint 		= 128; 
    public static const ULTRA_VIOLETE:uint 	= 256; 
 
    //convenience const to enable all flags 
    public static const ALL:uint = ULTRA_RED | RED | ORANGE | YELLOW | GREEN | BLUE | INDIGO | VIOLETE | ULTRA_VIOLETE; 
 
    public static function test(flags:uint, testFlag:uint):Boolean 
    { 
        return (flags & testFlag) == testFlag;
    } 
 } 
} 

Now, you can pass a combination of flags around as one single argument. The flags are combined using the bitwise OR operator.

 
var chosenColours:uint = Colours.RED | Colours.BLUE | Colours.VIOLETE; 

Then later test to see if the flag you want is in that single argument.

 
if ( Colours.test(chosenColours, Colours.RED) ) 
    trace(“We have RED”); 
else 
    trace(“We don’t have RED”); 

Note the Colours.ALL const, which is just a convenient way to enable all the flags in one go. 

And that's it. Makes life very simple, less method arguments, less var declaration, less database columns if you store a configuration, less memory used. Very simple to implement and very useful!

How it works - creating Each of the constants that define the flags Colours.RED, Colours.YELLOW etc are all integers. The separate flags must be multiples of 2 (which will become clearer later), so they would be 1,2,4,8,16,32 etc. The bitwise OR looks at the binary representation of each integer and analyses each bit of each integer in turn. Each bit is treated as a Boolean flag. If the bit is 1, its on, if its 0 its off. The bitwise OR will look at all the corresponding bits of each value in the list, starting with the first bit, then the second etc. If any of the bits are 1, the resulting bit for that position is 1, if ALL are 0 the resulting bit for that position is 0.
        0001  ( decimal 1 )         0010  ( decimal 2 )         1000  ( decimal 8 ) Bitwise OR =         1011  ( decimal 11 )
So, looking down each column of bits, the OR checks if any are 1, if so, the resulting bit is 1, else its 0. So the output of ( 1 | 2 | 8 ) is 1011,which is decimal 11. As the integers are multiples of 2 you don’t get multiple “1” bits in the binary representation of any number so only 1 column is ever marked as “on” by any flag – as in the example above. If you added 0110 ( binary 10 ) to the example above it would end up with 2 columns marked as "on" for one flag, which would break the system as you could not then calculate if the resulting bit flag contained a specific flag, as explained below.


How it works - testing Now you have one value that represents multiple flags. The next step is to check if it contains a particular flag. This is very similar, except you reverse the process and use the bitwise operator AND (the ampersand &, not to be confused with the logical AND &&) This looks at the columns of bits, and if ALL of them are 1, the result is 1, if not its 0. In the same way, as the columns are unique due to multiples of 2, we can check if the combined integer contains our value.
        1011 (decimal 11 - our combined flags)         0010 (decimal 2 - the flag to check for) Bitwise AND =         0010 (decimal 2)
As only the 2nd (from right) column contined both “On” bits, the result is 0010, which is our decimal 2, the value we wanted to check! So you can easily check to see if your value is in the combined flags by doing the following.



var hasValue:Boolean = ((flags & value) == value)

Very useful stuff!

HTML Text in a Flex Alert box

A quick and easy way to render HTML text with the body of a Flex Alert box. There is no API to set the htmlText property of the Alert text field, but you can access it using the mx_internal namespace.

 
var title:String ="HTML Alert!"; 
var htmlBody:String = "This is my HTML message with <b>Bold</b> text and <br/> HTML formatting <b/>"; 
 var alert:Alert = Alert.show(str,  htmlBody);  // now target the Alert text field (after we have opened it) and set the HTML text property	
 
use namespace mx.core.mx_internal; 
IUITextField(alert.alertForm.textField).htmlText = htmlBody; 
 

Using namespaces for access control.

Using your own namespaces can be a good way to add another level of access control to class libraries that sits somewhere between public and internal.

If you want to expose methods to classes in different packages, but not make them readily available to the whole of the outside world then this is a good way to do it. The Flex framework itself makes quite heavy use of the mx_internal namespace for inter-package communication and undocumented APIs

First is to make the namespace. This can be done in an actionscript file that contains the following:

 
package com.as3offcuts.namespaces 
{ 
     public namespace offcuts_internal; 
} 

That's it. Now you can import this namespace in your classes and either declare methods using it instead of public/internal etc. or call methods from other classes using it. The following demonstrates using the new namespace on an instance method:

 
package com.as3offcuts.somepackage 
{ 
import com.as3offcuts.namespaces.offcuts_internal; 

use namespace offcuts_internal; 
 
public class SomeClass 
 { 
    offcuts_internal function doSomething():void 
    { 
        trace("something"); 
    } 
 } 
}

There are three elements in the above example. The first is to import the namespace, much as you would import a class. The second is the use namespace declaration, and the third is use it in place of public or internal or whatever.

To then access this method from another class simply repeat the first two steps (import the namespace and the 'use namespace ... ' line.) and then call the method as you would call a public or internal one.

 
package com.as3offcuts.otherpackage 
{ 
 import com.as3offcuts.namespaces.offcuts_internal; 
 
use namespace offcuts_internal; 
 
public class SomeOtherClass 
 { 
    public function SomeOtherClass() 
    { 
        var someClass:SomeClass = new SomeClass(); 
        someClass.doSomething(); 
     }
 }
}

In terms of access control, as mentioned above, this sits somewhere between public and internal. It would be nice if it was just library level, but in reality anyone can import your namespace and use all the methods. They would however need to know about the namespace in first place. On the flip side though, another use for this is undocumented APIs, in which case you may actually want other people to use it.

As a foot note, importing and using the mx_internal namespace opens up undocumented functionality in the Flex framework. As the mx_internal.as file warns though, these methods are liable to change in future releases.

Extending DateFormatter to add 'st', 'nd', 'rd', 'th' Support.

I recently found myself with the task of configuring a date format for a new client.  The format that was specced looked something like:

Wednesday 14th October, 13:33

It was at this point I realised there is no support for the 'th' (or 'st', 'nd', 'rd') part of a date in the Flex DateFormatter.

Rather than mess around with the string after it had been formatted, I had a poke around the DateFormatter's source code and decided to write an extended date formatter which added support for date suffixes. To achieve this I needed to extend three parts of the original DateFormatter.

1. The format method of DateFormatter. This doesn't need to change much, most of what it does is validate and process the date object or string that was passed to it, before creating a StringFormatter to do the rest of the work. Unfortunately it won't let you access the processed value before it sends it on to the StringFormatter, and what gets returned from that isn't always re-usable, so I've duplicated all the processing code in my overridden format method. I've then altered the parameters that get passed to the new StringFormatter with the following 2 points.

2. The private static constant VALID_PATTERN_CHARS that gets passed to the previously mentioned StringFormatter needs changing to add a new pattern character. This can't be overridden, so I define a new static constant that includes all the normal ones, plus 'T' to represent a date suffix.

3. The internal static method extractTokenDate of the DateBase class that gets passed to the previously mentioned StringFormatter needs to be able to handle our new 'T' character. To acheive this I created my own static method that first calls extractTokenDate in DateBase, and then handles any empty result that has a token of 'T' before returning that result. Using the new DateFormatter with a 'T' in the format string will default to adding the correct 'st', 'nd', 'rd', 'th' to a date. I added a little extra customisation into this with the static var CUSTOM_NUMBER_SUFFIXES.

This can be set to a 31 element array of any custom suffix that will be appended to the date matching it's index in the array plus one.