views:

31

answers:

1

I have a class which extends the Sprite object in as3. I need to be able to override the transform.matrix setter in this class but haven't been successful in doing so.

I've tried many things, along with creating my own separate class which extends the Transform class and then overrides its set matrix function, and set my transform = new CustomTransform(). Sadly this didn't work.

In code this is what i tried:

public class MyClass extends Sprite
{
     public function MyClass()
     {
          super(); transform = new MyTransform(this);
     }
}

class MyTransform extends Transform
{
    public function MyTransform(dp:DisplayObject)
    {
        super();
    }
    override public function set matrix(value:Matrix)
    {
        super.matrix = value;
        customcode();
    }
}

All help is greatly appreciated!

A: 

This seems to work:

public  class MyClass extends Sprite
{
    public function MyClass()
    {
        super();
        transform = new MyTransform(this,super.transform);
        // i'm drawing a rect just to see the results of scaling
        graphics.beginFill(0xff0000);
        graphics.drawRect(0,0,100,100);
        graphics.endFill();       
    }

    override public function get transform():Transform {
        var tmp:Transform;
        if(super.transform is MyTransform) {
            tmp = super.transform;
        } else {
            tmp = new MyTransform(this,super.transform);
        }

        return tmp;
    }

    override public function set transform(value:Transform):void {
        var tmp:Transform;
        if(value is MyTransform) {
            tmp = value;
        } else {
            tmp = new MyTransform(this,value);
        }
        super.transform = tmp;
    }

}

public class MyTransform extends Transform
{

    public function MyTransform(dp:DisplayObject,transf:Transform = null)
    {
        super(dp);
        if(transf) {
            for(var prop:String in transf) {
                this[prop] = transf[prop];
            }
        }
    }

    override public function set matrix(value:Matrix):void
    {
        super.matrix = value;
    //    customcode();
    }
}

Use:

    var sp:MyClass = new MyClass();

    var mat:Matrix = sp.transform.matrix;
    mat.scale(3,3); 
    trace(sp.transform);
    sp.transform.matrix = mat;

    addChild(sp);

The problem is that, even if you create and assign your tranform to be of type MyTransform, the getter returns a regular Transform object. There's something weird about how transform objects work in Flash (this is also true for SoundTransform, for instance). There's some kind of cache mechanism implemented in a rather lame way that forces you to reassign the instance if you want to commit your changes.

I mean this pattern:

        var t:Transform = mc.transform;
        //  do something with t
        mc.transform = t;

So I think this is related to why your code doesn't work as expected.

To get around this, I'm checking both in the setter and the getter if the trasnform object passed is of type MyTransform. If it is, I use it as is. If it's not, I create a MyTransform object and copy all of the properties from the original Transform. It'd be nice if the Transform class had a clone method, but it doesn't, so I implemented this simple copy mechanism. Not sure if this doesn't mess up with some internal state in Transform (could be the case). I haven't tested it apart from applying a scale, once. You might want to do it, as there could be other side effects I'm not considering. Also, this is probably not the most performant. But I can't think of another way to have your matrix setter called.

Edit

Using a static/global dispatcher is not a good idea except you really need it to be global. Implementing IEventDispatcher, since you can't directly extend EventDispatcher, is what you want.

The code needed for that is a bit verbose, but it's a no-brainer anyway. All you need is having an internal instance of event dispatcher and implement the methods of the interface. In said methods, you forward the parameteres to the actual dispatcher.

    public class MyTransform extends Transform implements IEventDispatcher
{
    private var _dispatcher:EventDispatcher;

    public function MyTransform(dp:DisplayObject,transf:Transform = null)
    {
        super(dp);
        _dispatcher = new EventDispatcher(this);
        if(transf) {
            for(var prop:String in transf) {
                this[prop] = transf[prop];
            }
        }
    }

    override public function set matrix(value:Matrix):void
    {
        super.matrix = value;
    //    customcode();
    }

    public function dispatchEvent(event:Event):Boolean {
        return _dispatcher.dispatchEvent(event);
    }

    public function addEventListener(type:String,listener:Function,useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
        _dispatcher.addEventListener(type,listener,useCapture,priority,useWeakReference);
    }

    public function removeEventListener(type:String,listener:Function,useCapture:Boolean = false):void {
        _dispatcher.removeEventListener(type,listener,useCapture);
    }

    public function hasEventListener(type:String):Boolean {
        return _dispatcher.hasEventListener(type);
    }

    public function willTrigger(type:String):Boolean {
        return _dispatcher.willTrigger(type);
    }

}
Juan Pablo Califano
Yeah that seems to work with multiple transformations applied! Just one thing, I was thinking of firing an event once this happens (so i can run a function in my main class), but the Transform class doesnt have an EventDispatcher. Any ideas?
Fox
Nevermind, finally figured it out. For anyone interested the method used in the following link is basically what i did.http://www.gskinner.com/blog/archives/2007/07/building_a_stat_1.html
Fox
Glad it worked. I don't think using a global/static dispatcher is good idea though. You're better off implementing IEventDispatcher and making your MyTransform objects able to dispatch events. Check my edit.
Juan Pablo Califano
Never knew about that, I didn't like how hacky the other method felt so I'm changing this now. Thanks for the great tip!
Fox