【问题标题】:How to override the transform.matrix setter如何覆盖 transform.matrix 设置器
【发布时间】:2010-08-13 21:45:05
【问题描述】:

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

我尝试了很多方法,包括创建自己的单独类,该类扩展 Transform 类,然后覆盖其设置矩阵函数,并设置我的 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();
    }
}

非常感谢所有帮助!

【问题讨论】:

    标签: actionscript-3 matrix overriding


    【解决方案1】:

    这似乎有效:

    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 也会返回一个常规的转换对象。变换对象在 Flash 中的工作方式有些奇怪(例如,SoundTransform 也是如此)。有某种缓存机制以相当蹩脚的方式实现,如果您想提交更改,它会强制您重新分配实例。

    我的意思是这种模式:

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

    所以我认为这与您的代码无法按预期工作的原因有关。

    为了解决这个问题,如果传递的 trasnform 对象是 MyTransform 类型,我会同时检查 setter 和 getter。如果是,我按原样使用它。如果不是,我创建一个 MyTransform 对象并从原始 Transform 中复制所有属性。如果 Transform 类有一个 clone 方法就好了,但它没有,所以我实现了这个简单的复制机制。不确定这是否不会与 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);
        }
    
    }
    

    【讨论】:

    • 是的,这似乎适用于应用了多个转换!只是一件事,我想一旦发生这种情况就触发一个事件(这样我就可以在我的主类中运行一个函数),但是 Transform 类没有 EventDispatcher。有什么想法吗?
    • 没关系,终于想通了。对于任何感兴趣的人,以下链接中使用的方法基本上就是我所做的。 gskinner.com/blog/archives/2007/07/building_a_stat_1.html
    • 很高兴它成功了。我不认为使用全局/静态调度程序是个好主意。你最好实现 IEventDispatcher 并使你的 MyTransform 对象能够调度事件。检查我的编辑。
    • 从来不知道,我不喜欢另一种方法的感觉,所以我现在正在改变它。感谢您的精彩提示!
    猜你喜欢
    • 1970-01-01
    • 2013-07-26
    • 2011-12-17
    • 2023-03-26
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    相关资源
    最近更新 更多