如何覆盖transform.matrix setter

时间:2010-08-13 21:45:06

标签: actionscript-3 matrix function-overriding

我有一个在as3中扩展Sprite对象的类。我需要能够覆盖此类中的transform.matrix setter,但是没有成功。

我尝试了很多东西,同时创建了我自己的单独的类,它扩展了Transform类,然后覆盖了它的set matrix函数,并设置了我的transform = new CustomTransform()。可悲的是,这没有用。

在代码中,这是我尝试过的:

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();
    }
}

非常感谢所有帮助!

1 个答案:

答案 0 :(得分:0)

这似乎有效:

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();
    }
}

使用:

    var sp:MyClass = new MyClass();

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

    addChild(sp);

问题在于,即使您创建并将转换分配为MyTransform类型,getter也会返回常规的Transform对象。关于变换对象如何在Flash中工作有一些奇怪的东西(例如,对于SoundTransform也是如此)。如果要提交更改,则会以相当蹩脚的方式实现某种缓存机制,这会强制您重新分配实例。

我的意思是这种模式:

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

所以我认为这与你的代码无法正常工作的原因有关。

为了解决这个问题,如果传递的trasnform对象是MyTransform类型,我会在setter和getter中检查。如果是,我按原样使用它。如果不是,我创建一个MyTransform对象并复制原始Transform中的所有属性。如果Transform类有一个克隆方法会很好,但它没有,所以我实现了这个简单的复制机制。不确定这是否不会破坏Transform中的某些内部状态(可能就是这种情况)。我没有测试它除了应用刻度,一次。您可能想要这样做,因为可能会有其他副作用我不考虑。此外,这可能不是最高效的。但我想不出另一种方法来调用你的矩阵设置器。

修改

使用静态/全局调度程序并不是一个好主意,除非你真的需要它是全局的。实现IEventDispatcher,因为你不能直接扩展EventDispatcher,就是你想要的。

这需要的代码有点冗长,但无论如何它都是明智的。您所需要的只是拥有事件调度程序的内部实例并实现接口的方法。在所述方法中,您将参数转发给实际的调度程序。

    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);
    }

}