ActionScript 3 のフィルターについて。

以前、HiSprite クラスという、フィルター関連の設定をプロパティで行えるようにしたクラスを作成しました。ただ、これだと Sprite を継承した独自クラスなどに適用できません。ですので、この場合は委譲用クラスを実装した方が実用的だと考えました。しかし、ことごとく壁にぶち当たり、結論から言うと断念。

そんなこんなを twitter で愚痴っていると、nium 先生と beinteractive 先生からアドバイスを頂きました。「元オブジェクトに触られた場合に整合性を取ることは委譲の永遠の課題」というコメントなどはとても参考になり、ありがたかったです。この場を借りてお礼申し上げます。両先生、ありがとうございました!

以下、色々試してみたメモ。
3. 辺りはまだ望みがありそうなので、今後も試してみる予定です。


1. 委譲元の filters プロパティから適用済みのフィルターを判別して実装。

適用済みのフィルターを判別する際に問題が発生。filters プロパティは getter 内で中身のフィルターまで clone() しちゃってる模様。以下、検証用コード。

package
{
    import flash.display.Sprite;
    import flash.filters.BlurFilter;

    public class Document extends Sprite
    {
        public function Document ():void
        {
            var blur:BlurFilter = new BlurFilter();
            filters = [blur];

            trace("trace :", filters[0], filters[0]);
            // trace : [object BlurFilter] [object BlurFilter]

            trace("trace :", filters[0] == filters[0]);
            // trace : false
        }
    }
}

描画処理のために配列を直接操作されたくないのだとは思うのですが、それならば setter 内で clone() して処理しててくれればよかったのに・・・と思うわけで。そこで、試しにもう一つ検証用コード。

package
{
    import flash.display.Sprite;
    import flash.filters.BlurFilter;

    public class Document extends Sprite
    {
        public function Document ():void
        {
            var blur:BlurFilter = new BlurFilter();
            blur.blurX = 10;
            filters = [blur];
            blur.blurX = 100;

            trace("trace :", filters[0].blurX);
            // trace : 10
        }
    }
}

setter 内でもしっかり clone() されているみたいですね。描画処理のために、こればっかりはしょうがないんだなぁ、きっと。

2. 委譲用クラスのために BitmapFilter 系クラスを継承したクラスを独自実装。

独自実装するフィルタークラスは internal なり独自のネームスペースなりでかくまっておいて、 clone メソッドをオーバーライドして自分自身を返すようにしてしまおうと試みたのですが、そもそも BitmapFilter 系クラスは final されてて継承できませんでした。わぉ、盲点。

3. Proxy クラスで委譲用クラスのためのフィルタークラスを実装。

と思ったらすでに試されている方がいらっしゃいました。しかし、filters は setter 内でクラス判別を行っているため、結局は駄目な模様。

4. 委譲元の filters プロパティの奥地に委譲用のフィルターを格納。

これも失敗。以下、検証用コード。

package
{
    import flash.display.Sprite;
    import flash.filters.BlurFilter;

    public class Document extends Sprite
    {
        public function Document ():void
        {
            var blur:BlurFilter = new BlurFilter();
            var array:Array = [];

            // これは代入しても大丈夫。
            //array[0] = array;

            // これは代入すると Error がスローされる。
            array[100] = array;

            filters = array;
        }
    }
}

filters プロパティに代入する配列は綺麗に 0 から格納されてないと駄目でした。

Leave a Reply