Почему EventListeners перестают работать после манипулирования z-свойством и изменения stage.quality? - PullRequest
3 голосов
/ 16 сентября 2011

В настоящее время одна из наших команд страдает от очень странного явления: после манипулирования свойством z MovieClip и изменения качества сцены некоторые слушатели событий вложенного MovieClips, кажется, исчезают (или, по крайней мере, не реагируют направильные события больше).

Проблема также только появляется при выполнении обоих, изменяя качество сцены и , манипулируя свойством z.

Вот простой класс, демонстрирующий проблему:

package {
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.StageQuality;
import flash.events.MouseEvent;

public class StageQualityTestDemo extends MovieClip {
    private static const OVER_COLOR:uint = 0x13ff37;
    private static const OUT_COLOR:uint = 0x000000;
    private static const BACK_COLOR:uint = 0xdeadc0de;
    private var _qualitySetting:int = 0;
    private var _zoom:Number = 0.0;
    private var _mainsprite:MovieClip = new MovieClip();
    private var _button:MovieClip = new MovieClip();


    public function StageQualityTestDemo() {
        initDemo();
    }

    private function initDemo():void {
        this.addChild(_mainsprite);
        _mainsprite.addChild(_button);

        this.stage.addEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);
        stage.quality = StageQuality.LOW;
        stage.align = StageAlign.TOP_LEFT;
        stage.scaleMode = StageScaleMode.NO_SCALE;
        drawButtonCircle(OUT_COLOR);
        drawMainBackground(BACK_COLOR);
        _button.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOver);
        _button.addEventListener(MouseEvent.MOUSE_OUT, handleMouseOut);
    }

    private function handleMouseOver(event:MouseEvent):void {
        drawButtonCircle(OVER_COLOR);
    }

    private function handleMouseOut(event:MouseEvent):void {
        drawButtonCircle(OUT_COLOR);
    }

    private function drawMainBackground(color:uint):void {
        var g:Graphics = _mainsprite.graphics;
        g.clear();
        g.beginFill(color);
        g.drawRect(0, 0, 500, 500);
        g.endFill();
    }

    private function drawButtonCircle(color:uint):void {
        var g:Graphics = _button.graphics;
        g.clear();
        g.beginFill(color);
        g.drawCircle(250, 250, 50);
        g.endFill();
    }

    private function handleMouseWheel(event:MouseEvent):void {
        var motion:Number = event.delta * 5;
        _zoom += motion;
        _mainsprite.z = _zoom;

        if (_zoom < 0 && _qualitySetting != 0 ) {
            _qualitySetting = 0;
            trace("setting LOW");
            stage.quality = StageQuality.LOW;
        }

        if (_zoom > 100 && _qualitySetting == 0 ) {
            _qualitySetting = 1;
            trace("setting HIGH");
            stage.quality = StageQuality.HIGH;
        }
    }
}
}

Может кто-нибудь дать мне указатель, что, черт возьми, происходит здесь?Почему списки событий на _button перестают работать при уменьшении масштаба и сценического качества HIGH, но работают снова при увеличении масштаба и сценическом качестве LOW?Помогите?Кто-нибудь?


[Обновление]

Основываясь на предложении @Amy Blankenship, я добавил еще несколько trace утверждений.В результате и willTrigger(), и hasEventListener() сообщают об истине, но функции обработчика по-прежнему не вызываются.

Изменения кода:

[...]

private var _counter:int;

[...]

private function initDemo():void {
    this.addChild(_mainsprite);
    _mainsprite.addChild(_button);
    this.stage.addEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);
    this.stage.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
    stage.quality = StageQuality.LOW;
    stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;
    drawButtonCircle(OUT_COLOR);
    drawMainBackground(BACK_COLOR);
    _button.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOver);
    _button.addEventListener(MouseEvent.MOUSE_OUT, handleMouseOut);
}

private function handleMouseMove(event:MouseEvent):void {
    if (_counter++ % 50 == 0) {
        trace("_button.willTrigger(MouseEvent.MOUSE_OVER): " + _button.willTrigger(MouseEvent.MOUSE_OVER));
        trace("_button.willTrigger(MouseEvent.MOUSE_OUT): " + _button.willTrigger(MouseEvent.MOUSE_OVER));
        trace("_button.hasEventListener(MouseEvent.MOUSE_OVER): " + _button.hasEventListener(MouseEvent.MOUSE_OVER));
        trace("_button.hasEventListener(MouseEvent.MOUSE_OUT): " + _button.hasEventListener(MouseEvent.MOUSE_OUT));
    }
}

private function handleMouseOver(event:MouseEvent):void {
    trace("handleMouseOver");
    drawButtonCircle(OVER_COLOR);
}

private function handleMouseOut(event:MouseEvent):void {
    trace("handleMouseOut");
    drawButtonCircle(OUT_COLOR);
}

[...]

Вывод трассировки:

_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
// moving the mouse over and off _button
handleMouseOver
handleMouseOut
_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
// zooming out; handler methods no longer called
setting HIGH
_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
// zooming back in; handler methods called again
setting LOW
handleMouseOver
handleMouseOut
_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
handleMouseOver
_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
handleMouseOut
_button.willTrigger(MouseEvent.MOUSE_OVER): true
_button.willTrigger(MouseEvent.MOUSE_OUT): true
_button.hasEventListener(MouseEvent.MOUSE_OVER): true
_button.hasEventListener(MouseEvent.MOUSE_OUT): true
handleMouseOver
handleMouseOut

[/ Update]

Ответы [ 4 ]

3 голосов
/ 19 сентября 2011

Я считаю, что используя stage.quality = StageQuality.MEDIUM;вместо HIGH работает.Я знаю, что преобразования Flash z фактически работают путем преобразования клипов в растровые изображения.И эти растровые изображения не являются объектами InteractiveObject.Я думаю, что вы нашли ошибку флэш-плеер.Но мы надеемся, что использование среднего уровня качества для увеличенных элементов даст вам «достаточно хорошее» качество для завершения вашего проекта.

2 голосов
/ 20 сентября 2011

Я также в растерянности относительно , почему такое поведение происходит, но я смог найти обходной путь.

Реконструкция списка отображения позволяет вам снова использовать события мыши. Я не знаю, насколько это практично для вашей ситуации; Вы упомянули, что это упрощенная версия вашей проблемы. Независимо от того, вот код, который я запускаю. Я могу увеличивать и изменять качество сцены, продолжая обрабатывать события мыши:

package
{
    import flash.display.Graphics;
    import flash.display.MovieClip;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.utils.getTimer;

    public class AS3Playground extends MovieClip
    {
        private static const OVER_COLOR:uint = 0x13ff37;
        private static const OUT_COLOR:uint = 0x000000;
        private static const BACK_COLOR:uint = 0xdeadc0de;
        private var _qualitySetting:int = 0;
        private var _zoom:Number = 0.0;
        private var _mainsprite:MovieClip;
        private var _button:MovieClip;

        private var _lastKnownStageQuality:String;

        private var _counter:int;

        public function AS3Playground()
        {
            trace("AS3Playground() @"+getTimer());
            initDemo();
        }

        private function maintainDisplayOrder():void
        {
            addChild(_mainsprite);
            _mainsprite.addChild(_button);
        }

        private function initDemo():void
        {
            trace("initDemo() @"+getTimer());

            _mainsprite  = new MovieClip();
            _mainsprite.graphics.clear();
            _mainsprite.graphics.beginFill(BACK_COLOR);
            _mainsprite.graphics.drawRect(0, 0, 500, 500);
            _mainsprite.graphics.endFill();

            _button = new MovieClip();
            _button.graphics.clear();
            _button.graphics.beginFill(OUT_COLOR);
            _button.graphics.drawCircle(250, 250, 50);
            _button.graphics.endFill();

            maintainDisplayOrder();

            stage.quality = StageQuality.LOW;
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            _lastKnownStageQuality = stage.quality;

            stage.addEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);
            _button.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOver);
            _button.addEventListener(MouseEvent.MOUSE_OUT, handleMouseOut);
            addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true);
        }

        private function onEnterFrame(event:Event):void
        {
            if (_counter++ % 50 == 0)
            {
                trace("onEnterFrame(event) @"+getTimer());
                trace("_button.willTrigger(MouseEvent.MOUSE_OVER): " + _button.willTrigger(MouseEvent.MOUSE_OVER));
                trace("_button.willTrigger(MouseEvent.MOUSE_OUT): " + _button.willTrigger(MouseEvent.MOUSE_OVER));
                trace("_button.hasEventListener(MouseEvent.MOUSE_OVER): " + _button.hasEventListener(MouseEvent.MOUSE_OVER));
                trace("_button.hasEventListener(MouseEvent.MOUSE_OUT): " + _button.hasEventListener(MouseEvent.MOUSE_OUT));
                trace("mouse: @("+mouseX+", "+mouseY+")");

                var buttonStageRect:Rectangle = new Rectangle();
                var buttonStageCoordinate:Point = _button.localToGlobal(new Point(0, 0));
                buttonStageRect.x = buttonStageCoordinate.x;
                buttonStageRect.y = buttonStageCoordinate.y;

                trace("_button stage area: @("+buttonStageRect.x+", "+buttonStageRect.y+") "+_button.width+"x"+_button.height);
                trace("hitTest? "+_button.hitTestPoint(mouseX, mouseY));
            }

            if (_lastKnownStageQuality != stage.quality)
            {
                trace("stage quality changed!");    
                maintainDisplayOrder();
                _lastKnownStageQuality = stage.quality;
            }
        }

        private function handleMouseOver(event:MouseEvent):void
        {
            trace("handleMouseOver(event) @"+getTimer());
            drawButtonCircle(OVER_COLOR);
        }

        private function handleMouseOut(event:MouseEvent):void
        {
            trace("handleMouseOut(event) @"+getTimer());
            drawButtonCircle(OUT_COLOR);
        }

        private function drawButtonCircle(color:uint):void
        {
            _button.graphics.clear();
            _button.graphics.beginFill(color);
            _button.graphics.drawCircle(250, 250, 50);
            _button.graphics.endFill();
        }

        private function handleMouseWheel(event:MouseEvent):void
        {
            trace("handleMouseWheel(event) @"+getTimer());
            var motion:Number = event.delta * 5;
            _zoom += motion;
            _mainsprite.z = _zoom;

            if (_zoom < 0 && _qualitySetting != 0 )
            {
                _qualitySetting = 0;
                trace("setting LOW");
                stage.quality = StageQuality.LOW;
            }
            if (_zoom > 100 && _qualitySetting == 0 )
            {
                 _qualitySetting = 1;
                 trace("setting HIGH");
                 stage.quality = StageQuality.HIGH;
            }

            maintainDisplayOrder();
        }
    }
}
1 голос
/ 25 сентября 2011

Проблема разрешилась после того, как команда, в которой изначально возникла ошибка, провела еще несколько тестов и расследований. В своем вопросе я упомянул, что показанный код является лишь упрощенной демонстрацией проблемы.

Оригинальный продукт представляет собой приложение Flex 4.1 и использует векторную графику. При масштабировании или панорамировании карты мы переключаем stage.quality на НИЗКИЙ, потому что разница едва заметна, но с НИЗКИМ качеством все значительно быстрее.

Эта ошибка доставила много хлопот команде, поскольку некоторые кнопки во всплывающих окнах не реагировали, что в основном нарушало некоторые основные функции игры. Тем не менее, проблема, очевидно, была связана с некоторым эффектом постепенного появления этих всплывающих окон. Команда убрала переход, и теперь все работает хорошо ... o_O

«Flash Player, вы не работаете, как обычное программное обеспечение?»

Я сообщил о проблеме в Adobe , и она была подтверждена как ошибка. Я уже попросил нашу другую команду предоставить подробный отчет об обстоятельствах, в которых появилась ошибка, чтобы прикрепить ее к отслеживаемой ошибке, поэтому когда-нибудь в течение следующей недели будет доступна дополнительная информация по этой проблеме.

Спасибо всем за ваши советы и предложения. :)

1 голос
/ 20 сентября 2011

Я полагаю, это может быть вашей проблемой.Flash НЕ поддерживает событие MOUSE_WHEEL.

Существует обходной путь, использующий код JavaScript и ExternalInterface.По сути, JavaScript перехватывает событие колеса мыши и передает его объекту Flash под курсором.

Вот исходный код, который решает эту проблему (включая комментарии: http://code.google.com/p/contentdisplay/source/browse/trunk/source/com/earthbrowser/ebutils/MacMouseWheelHandler.as?r=20

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...