如何重写的transform.matrix二传手重写、二传、transform、matrix

2023-09-08 15:28:28 作者:最美不过初遇见

我有在AS3扩展Sprite对象的类。我需要能够覆盖在这个类的的transform.matrix二传手,但都没有成功这样做。

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.

我尝试过很多事情,一起创建延伸的变换类,然后覆盖其设置的矩阵功能,我自己单独的类,并设置我的变换=新CustomTransform()。遗憾的是并没有工作。

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.

在$ C C $这是我的尝试:

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

所有的帮助是极大的AP preciated!

All help is greatly appreciated!

推荐答案

这似乎工作:

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的,吸气返回定期变换对象。有一些奇怪的关于如何变换对象的工作在Flash(这也是如此的SoundTransform,例如)。有某种缓存机制,迫使你,如果你想提交你的修改重新分配的情况相当蹩脚的方式实现。

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.

我的意思是这种模式:

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

所以我觉得这是关系到为什么你的code并不如预期。工作

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

要解决这个问题,我在二传手和吸气检查双方是否通过了trasnform对象类型MyTransform的。如果是,我把它当作是。如果不是的话,我创建了一个MyTransform对象,并复制所有的属性从原来的变换。这将会是很好,如果变换类有一个克隆的方法,但它并没有,所以我实现了这个简单的复制机制。不知道这不惹了一些内部状态的转换(可能是这样)。我没有从应用的规模,一旦测试它拆开。你可能会想这样做,因为可能会有其他副作用,我不考虑。此外,这可能不是最高效的。但我不能想别的办法让你叫矩阵的制定者。

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.

修改

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

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.

需要注意,code是一个有点冗长,但它是一个没有脑子呢。所有你需要的是有事件调度程序的内部实例和实现接口的方法。在所述的方法中,则转发parameteres实际调度

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

}