PDA

Просмотр полной версии : реализация постпроцессинга


myakushka
11.02.2014, 13:34
Здрасьте.
Есть объект, который имеет несколько настроек и состояние. Настройки изменяются извне. Обновить состояние извне невозможно. Если хоть одна из настроек изменилась, то нужно обновить состояние объекта. Класс объекта расширяет EventDispatcher.
Задача - сделать одно обновление состояния объекта после изменения одной или нескольких настроек за кадр.
хэлпмиплиз:)

Zebestov
11.02.2014, 14:09
Самый простой и распространенный способ — хранить timestamp в модели (где меняются данные) и в отображении (где отображается текущее состояние). При изменении модели пиши в timestamp модели текущее время. В отображении же в каждом новом кадре сравнивай значение timestamp с его аналогом в модели. Если в модели он оказался больше, значит с момента последней "перерисовки" модель изменилась. Следовательно нужно "перерисоваться" и записать в timestamp отображения значение из модели.

myakushka
11.02.2014, 14:25
Спасибо за способ, возьму на заметку.
Но проблема немного иная. Я могу манипулировать только объектами модели. Доступа к объектам отображения нет, сл-но и к событиям смены кадров тоже. И обновлять нужно не объекты отображения, а объекты модели.

Zebestov
11.02.2014, 14:52
Доступа к объектам отображения нет, сл-но и к событиям смены кадров тоже.
Что значит нет доступа — код объекта недоступен для изменения? Это скомпилированная кем-то SWC/SWF?

myakushka
11.02.2014, 15:38
Нет, просто у меня mvc)
В модели не содержится отображаемых объектов и заводить их там нельзя:
- нельзя создавать фэйковый шейп, который будет являться проводником для enter_frame
- нельзя протягивать в модель снаружи какой-либо контейнер отображаемых объектов для тех же целей.
"нельзя" всмысле не хочу и не буду:)

Zebestov
11.02.2014, 15:41
Ну так я тебе и рассказал как поступать в рамках MVC. Проверка timestamp модели и отображения производятся в отображении:

1. оно имеет ссылку на модель и может дернуть геттер timestamp
2. оно знает, когда новый кадр

Что не так?

myakushka
11.02.2014, 16:09
Проверка timestamp модели и отображения производятся в отображении

Мы друг друга пока не поймем:)
Отображение сейчас трогать вообще не надо. У меня настройка одного из объектов в моделе производится в несколько этапов. И после этих настроек ему нужно обновить своё внутреннее состояние (не отображение).

Akopalipsis
11.02.2014, 16:13
Покажите минимальный пример, а то не понятно. Вам нужно обновлять вложенный объект, но так-как он внизу иерархии, события ему не послать, так?

silin
11.02.2014, 17:15
>>И после этих настроек ему нужно обновить своё внутреннее состояние
как вариант: каждая из настроек запускает апдейт с неким таймаутом, сбрасывая предыдущий запуск
clearTimeout(id);
id=setTimeout(finalizeAdjust, 20);
т.е. обновление выполнится только один раз при любом изменении, если об этом речь

Zebestov
11.02.2014, 17:19
Отображение сейчас трогать вообще не надо.
Понял. Значит при внесении отдельных изменений устанавливать флаг изменений. А когда наступает время "обновиться" (в каждом кадре?) смотрим на этот флаг, если он указывает, что были внесены изменения, обновляемся. В конце флаг снова сбрасывается.
Хочешь ты или нет, но если тебе нужно менять модель раз в кадр, то она должна иметь либо публичный метод, который мы будем дергать покадрово, либо сама следить за событием ENTER_FRAME (EXIT_FRAME) какого-то DisplayObject.

myakushka
11.02.2014, 17:39
Вопрос по таймауту: какое время задержки нужно задавать, чтобы метод finalizeAdjust выполнился после всего остального кода в текущем кадре?
Если я правильно понимаю, то любого минимального времени (например 1 млс) будет вполне достаточно. Так как выполнение стэка команд в кадре разрываться не может и команда на выполнение метода finalizeAdjust просто добавится в конец. Заапрувьте или поправьте моё понимание

silin
11.02.2014, 17:48
не могу ничего внятного по времени сказать
1 млс это все равно те же 16 мс - типа частота системного таймера в винде, например, а в плеере это может быть вообще что угодно.., ну и потом насколько это принципиально - обновится через 10 или 40 мс ?

carrotoff
11.02.2014, 17:59
Это все-таки неверный подход, по моему мнению. Если есть зависимость от смены кадров - нужно работать с этим событием, а не придумывать костыли в виде:
какое время задержки нужно задавать

Вопрос вашей архитектуры - как протаскивать событие смены кадров.
Можно сделать какой-нибудь глобальный броадкастер, как, например, здесь (http://blooddy.googlecode.com/svn/trunk/blooddy_core/src/by/blooddy/core/utils/enterFrameBroadcaster.as)

myakushka
11.02.2014, 18:00
я просто хочу понять как работает этот таймаут.
если, например, я укажу setTimeout(finalizeAdjust, 20);, а время выполнения последующего кода в этом кадре составит 60 мс, то метод finalizeAdjust выполнится через 60? или через 20 мс выполнение стэка команд в кадре прервется и выполнится метод finalizeAdjust?

Добавлено через 11 минут
carrotoff, собственно сейчас почти так и сделал. Слушаю событие смены кадров через глобальный статический инстанс

Zebestov
11.02.2014, 20:43
метод finalizeAdjust выполнится через 60?
Ага.

или через 20 мс выполнение стэка команд в кадре прервется и выполнится метод finalizeAdjust?
Неа.

Hauts
11.02.2014, 21:02
carrotoff прав.

Таймаут совсем уж как-то костыльно, по моему мнению.

silin
11.02.2014, 22:14
информация к размышлению
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.*;

[SWF( frameRate="40")]
public class Test extends Sprite
{
private var log:String = "";
private var id:int;

public function Test()
{
addEventListener(Event.ENTER_FRAME, enterFrame);
}

private function enterFrame(e:Event):void
{

_trace("enterFrame \t" + new Date().getMilliseconds());
if (!id)start();
}

private function start():void
{
_trace("start \t\t\t" + time());
id = setTimeout(traceTime, 10, 10);
setTimeout(traceTime, 40, 40);
setTimeout(traceTime, 80, 80);
setTimeout(traceTime, 160, 160);

setTimeout(stop, 400);

// если нет вычислений в кадре, то таймауты разбредутся по enterFrame
// если нагрузить, то все просроченные таймауты выполнятся до ближайшего enterFrame
// for (var i:int = 0; i <1e7 ; i++) if(!(i%1e6))_trace( "loop \t\t\t"+ time() );

}

private function stop():void
{
removeEventListener(Event.ENTER_FRAME, enterFrame);
var tf:TextField = new TextField();
tf.autoSize = TextFieldAutoSize.LEFT;
tf.text = log;
addChild(tf);
}

private function _trace(s:String):void
{
log += s + "\n";
}

private function traceTime(val:Number):void
{
_trace("timeOut_" + val + " \t" + time());

}

private function time():Number
{
return new Date().getMilliseconds();
}
}

}
хотя это, конечно, ничего не доказывает - раз поведение таймеров не документировано никак, то и ручаться за однозначность не выходит

myakushka
12.02.2014, 12:29
всем спасибо:)