Filters Manager in AS3 (BitmapEffects Manager) or how to add, remove and modify a filter from a DisplayObject

0 Flares Twitter 0 Facebook 0 Google+ 0 Email -- Filament.io 0 Flares ×

First of all, to understand the need of a centralized manager for filters in flash, we need to understand how filters are set on a DisplayObject.

To set a filter, we first need to create a BitmapFilter object :

[sourcecode language=’as3′]
// create a new blur filter
var blur:BlurFilter = new BlurFilter(4.0, 4.0, 1);
[/sourcecode]

Then add it to the “filters” property (which is an array) of a DisplayObject like so:

[sourcecode language=’as3′]
// get a copy of the “filters” array
var aFilters:Array = displayObject.filters;
// add our filter to our new array
aFilters.push(blur);
// and set our new array
displayObject.filters = aFilters;
[/sourcecode]

Why do we need to do so ? because flash actually makes a copy of the filters array when it is set (function set) and so the array we are accessing when getting the “filters” property of a DisplayObject is not the actual array flash is using to apply the filters but a duplicate.
Thus, we need to get the array containing the filters being applied to a DisplayObject, push the new filter in and re-set the “filters” property with the new Array object containing our new filter object.

Another thing is that the filters contained in that “filters” array are not the actual references of the filters being applied to the DisplayObject but again, duplicates of them.
So, when we need to modify or remove a specific filter from the list, we won’t be able to do it like this:

[sourcecode language=’as3′]
// modify a filter
displayObject.filters[0].blurX = 8.0;

// or remove it
displayObject.filters.splice(0, 1);
[/sourcecode]

How to do it then ?… by keeping a copy of all the filters being applied to a DisplayObject in a separate Array. And this is exactly what the Filters Manager does.

Here is the source code of the class I’m currently using (it is not complete and can be seen more as a base class):

[sourcecode language=’as3′]
package rabbit.managers.filters
{
import flash.display.DisplayObject;
import flash.filters.BitmapFilter;
import flash.utils.Dictionary;

/**
* Singleton class
* @author Thomas John (thomas.john@open-design.be) www.open-design.be
*/
public class FiltersManager
{
// our unique instance of this class
private static var instance:FiltersManager = new FiltersManager();

private var dFilters:Dictionary = new Dictionary();

/**
* Constructor : check if an instance already exists and if it does throw an error
*/
public function FiltersManager()
{
if ( instance ) throw new Error( “FiltersManager can only be accessed through FiltersManager.getInstance()” );
// init

}

/**
* Get unique instance of this singleton class
* @return                    Instance of this class
*/
public static function getInstance():FiltersManager{
return instance;
}

public function add(target:DisplayObject, filter:BitmapFilter):void
{
var tmp:Array = dFilters[target] as Array;
if ( tmp == null ) tmp = dFilters[target] = target.filters;

tmp.push(filter);
target.filters = tmp;
}

public function remove(target:DisplayObject, filter:BitmapFilter):void
{
var tmp:Array = dFilters[target] as Array;
if ( tmp == null ) tmp = dFilters[target] = target.filters;

var index:int = indexOf(tmp, filter);
if ( index < 0 ) return; tmp.splice(index, 1); target.filters = tmp; } public function indexOf(filters:Array, filter:BitmapFilter):int { var index:int = filters.length; var f:BitmapFilter; while(index--) { f = filters[index]; if (f == filter) return index; } return -1; } } } [/sourcecode] This is a singleton, meaning there can be only one instance of this class and can be accessed anywhere in your projet like this: [sourcecode language='as3'] public var filtersManager:FiltersManager = FiltersManager.getInstance(); [/sourcecode] This is really only a base and lots of functions can be added to make it really easy to manage filters without having to keep a reference to the filters we want to modify or remove. But the base is set. Hope it will be of any help!

0 Flares Twitter 0 Facebook 0 Google+ 0 Email -- Filament.io 0 Flares ×

4 Comments

  1. I think I have a better solution for this.
    It\’s not in a class, but it doesn\’t have to.
    Anyway, here it is:

    <cite>
    var dic=new Dictionary();
    DisplayObject.prototype.applyFilter = function (filter) {
    if (!dic[this]) dic[this]=this.filters;
    dic[this].push(filter); trace(\"apply\"+(dic[this].length-1))
    this.filters=dic[this];
    }
    DisplayObject.prototype.removeFilter = function (filter) { trace(dic[this].indexOf(filter));
    dic[this].splice(dic[this].indexOf(filter), 1);
    this.filters=dic[this];
    }
    </cite>

  2. admin

    yep you’re right, it could be done like that too but I just prefer the class structure. More readable, auto-completion in FlashDevelop, etc…

  3. Aimeric

    This will help developping my prototype, but I certainly will knit one of my own so it has more fancyness to it.

    Thank you very much, its all very helpful [ I think I use your eventManager too 😉 ]

  4. admin

    You’re welcome !
    I’ve done a more advanced manager, I’ll try to put it online soon (1 week… ;))

Leave a Comment

*