Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Изменение свойств фильтра(ов) (http://www.flasher.ru/forum/showthread.php?t=177095)

TanaTiX 24.03.2012 13:15

Изменение свойств фильтра(ов)
 
Есть некий DisplayObject, на который действует неопределенное количество фильтров.
В какой-то момент необходимо один или несколько из них "обновить", т.к. они поменяли ряд своих значений.
Как, если предположительно неизвестно что и как поменялось?
Пример кода:
Код AS3:

import flash.display.Sprite;
import flash.filters.DropShadowFilter;
 
var mc:Sprite=new Sprite();
mc.graphics.beginFill(0xff0000);
mc.graphics.drawCircle(100,100,100);
mc.graphics.endFill();
addChild(mc);
 
var filter:DropShadowFilter = new DropShadowFilter();
mc.filters=[filter];
 
filter.distance=50;
//вот тут необходимо обновить фильтр/отображение объекта, с учетом того, что количество примененных фильтров и ссылки на них не известны


Wolsh 24.03.2012 14:26

Просто заново назначить массив фильтров... Или что именно неизвестно?
Код AS3:

var shadow:DropShadowFilter = new DropShadowFilter();
var blur:BlurFilter = new BlurFilter();
var blurShadow:Array = [shadow, blur];
 
mc.filters = blurShadow;
 
shadow.distance = 50;
mc.filters = blurShadow;


Deimos747 24.03.2012 14:27

Код AS3:

for each(var oldFilter: Object in mc.filters) {
  if (oldFilter is DropShadowFilter) {
      for (var prop: String in filter) {
          DropShadowFilter(oldFilter)[prop] = filter[prop]
      }
      break;
  }
}

Я думаю, как то так

Wolsh 24.03.2012 14:35

Массив-то хранит ссылки на экземпляры фильтров, и когда фильтры меняются, "в массиве" они "тоже меняются". Но дело в том, что когда Вы отдавали массив свойству filters, фильтры применяются один раз как набор эффектов с установками (значениями). Автоматического обновления не происходит, так же как здесь:
Код AS3:

var b:Number = 500;
mc.width = b; // применили, mc стал шириной 500
b = 1000; // но mc не стал шириной 1000 ))
mc.width = b; // а вот теперь 1000.


TanaTiX 24.03.2012 16:48

Wolsh, да, то что необходимо назначить, - не известно.
Массив - объект ссылочного типа, думал что по сеттеру происходит сравнение массивов. Но нижеприведенный код на результате никак не отразился:
Код AS3:

var arr:Array = mc.filters;
var newArr:Array=[];
for each(var item:Object in arr){
        newArr.push(item);
}
mc.filters = newArr;

Очень бы не хотелось воспользоваться чем-то похожим на вариант Deimos747

Wolsh 24.03.2012 19:10

А как он должен был отразиться? Если ты скопировал и назначил обратно то же, что и было?
Код AS3:

var filtersArr:Array = [_shadow, _blur];
mc.filters = filtersArr;
trace(mc.filters == filtersArr); // false !

Добавлено через 11 минут
Цитата:

Очень бы не хотелось воспользоваться чем-то похожим на вариант Deimos747
И не придется, ибо он не будет работать. Я вроде объяснил, почему. И как будет работать, ответил. Если не знаете, каким объектам какие фильтры поназначили, то это уж не моя вина. Как обычно – чините архитектуру.

Inet_PC 24.03.2012 19:29

Ну, а в чем проблема то? Нужно обновить фильтры в любой момент времени?
Код AS3:

if (mc && mc.filters) mc.filters = mc.filters.concat();

Конкат тут так на всякий случай. Если без него работает, то лучше без него. И чем Вас ответ Wolsh-а не устроил?

dimarik 24.03.2012 19:56

Нужно сначала получить фильтры, обновить их и засеттить заново.

Silicium 24.03.2012 21:19

Почему бы не переопределить сеттер для фильтров и в нем все это реализовывать?

Wolsh 24.03.2012 21:47

Silicium, отличная мысль!
FilteredSprite.as :
Код AS3:

package  
{
        import flash.display.Sprite;
        public class FilteredSprite extends Sprite
        {
                private var _filterArray:Array = [];
 
                public function FilteredSprite()
                {
 
                }
 
                override public function set filters(value:Array):void
                {
                        _filterArray = value;
                        super.filters = value;
                }
 
                public function updateFilters():void
                {
                        super.filters = _filterArray;
                }
        }
}

Код AS3:

var mc:FilteredSprite = new FilteredSprite();
mc.graphics.beginFill(0x000000, 1);
mc.graphics.drawRect(0, 0, 200, 150);
addChild(mc);
mc.x = mc.y = 100;
var filtersArr:Array = [_shadow, _blur];
mc.filters = filtersArr;
 
_shadow.distance = 80;
mc.updateFilters(); // работает


Silicium 25.03.2012 00:50

Спасибо:rolleyes:

Psycho Tiger 25.03.2012 13:10

Код AS3:

var filtersArr:Array = [_shadow, _blur];
mc.filters = filtersArr;
trace(mc.filters == filtersArr); // false !

Да, у него не только клонирующий сеттер, но и клонирующий геттер.

Wolsh 25.03.2012 14:03

Все гораздо хуже, Артём...
Код AS3:

var filtersArr:Array = [_shadow, _blur];
mc.filters = filtersArr;
trace(mc.filters[0] == _shadow); // false

В массиве из геттера ссылки не на исходные экземпляры фильтров. То есть не только экземпляр массива другой, сами фильтры были заново созданы где-то в глубинах подсознания ФП.

TanaTiX 25.03.2012 17:07

Цитата:

А как он должен был отразиться? Если ты скопировал и назначил обратно то же, что и было?
Не тоже. Изначально были назначены настройки по умолчанию, затем в фильтре изменили значение distance, т.е. тень, которая была сразу под объектам должна отодвинуться значительно в вышеуказанном примере. Этого не происходит, ни если следовать примеру Inet_PC-а, ни dimarik-а.
Совет Silicium-а интересен, но предполагается другой уровень абстракции. Код должен работать с тем что дают, а не использовать то, что есть.
Возвращаясь к 1му посту, если занести во временную переменную значение mc.filters, затем mc.filters назначить null и потом ему присвоить ранее помещенное во временную переменную значение - результата все равно нет.

Wolsh 25.03.2012 17:16

Может, Вам перечитать тему еще раз? Вдумчиво, например.

Добавлено через 8 минут
Обратите внимание на два блока кода выше на этой странице. Вдумайтесь в результаты трейса. Поймите, что DisplayObject не хранит ссылки на ваши фильтры в своем свойстве filters. После передачи ваших фильтров объекту вы можете менять их как угодно, можете их вообще удалить – ничего не изменится. А запросив "обратно" массив filters из объекта, Вы получите другой массив со ссылками на другие объекты, о которых Вы вообще ничего не знаете, которых никогда сами не создавали и в которых изменить ничего не могли.

i.o. 25.03.2012 17:36

Цитата:

Сообщение от Wolsh (Сообщение 1071025)
Все гораздо хуже, Артём...
Код AS3:

var filtersArr:Array = [_shadow, _blur];
mc.filters = filtersArr;
trace(mc.filters[0] == _shadow); // false

В массиве из геттера ссылки не на исходные экземпляры фильтров. То есть не только экземпляр массива другой, сами фильтры были заново созданы где-то в глубинах подсознания ФП.

Кэп намекает на BitmapFilter#clone()

Wolsh 25.03.2012 17:37

Цитата:

Код должен работать с тем что дают
Ну допустим устроить всем наследование не от Спрайта а от FilteredSprite тяжело или вообще неосуществимо. Но композицию-то сделать не проблема? Просто поместить объект внутрь FilteredSprite, в такой вот дизайнерский wrapper-декоратор, отвечающий за фильтрацию.
Ну либо как-то научиться запоминать, кому какие фильтры назначали. Почему это невозможно?

TanaTiX 25.03.2012 18:09

Wolsh, спасибо, что носом ткнул, это бывает очень полезно.
Странное поведение, по ходу действительно там клоны.

PS. wrapper-декоратор, отвечающий за фильтрацию, очень может быть.


Часовой пояс GMT +4, время: 10:57.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.