Как переопределить установщик transform.matrix - PullRequest
0 голосов
/ 14 августа 2010

У меня есть класс, который расширяет объект Sprite в as3. Мне нужно иметь возможность переопределить сеттер transform.matrix в этом классе, но мне это не удалось.

Я пробовал много вещей, наряду с созданием собственного отдельного класса, который расширяет класс Transform, а затем переопределяет его функцию set matrix и устанавливает my 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 голосов
/ 14 августа 2010

Кажется, что это работает:

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, метод получения возвращаетобычный объект Transform.Есть что-то странное в том, как объекты преобразования работают во Flash (например, это верно и для SoundTransform).Существует некоторый механизм кэширования, реализованный довольно неэффективно, который заставляет вас переназначить экземпляр, если вы хотите зафиксировать свои изменения.

Я имею в виду этот шаблон:

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

Так что я думаю, это связано с тем, почему ваш код не работает должным образом.

Чтобы обойти это, я 'Проверка как в установщике, так и в получателе, если переданный объект trasnform имеет тип MyTransform.Если это так, я использую это как есть.Если это не так, я создаю объект 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);
    }

}
...