Показаны сообщения с ярлыком Код. Показать все сообщения
Показаны сообщения с ярлыком Код. Показать все сообщения

воскресенье, марта 22, 2009

mx:Pause vs flash.utils.Timer. Flex

Декларативность MXML - огромное достоинство Flex.
Легкое определение переменных в MXML значительно упрощает разработку:
  • позволяет легко и наглядно определять их свойства и обработчики событий
  • автоматически делает переменные Bindable
  • позволяет их связать с другими переменными и выражениями
  • делает наглядным код

Но, на сколько я понял, не все классы можно представить в декларативном виде.

Например, класс flash.utils.Timer невозможно представить в виде MXML. Компилятор выдает ошибку "Неправильное количество аргументов". Всё от того, что конструктор этого класса содержит один обязательный параметр. Как его указать, и возможно ли это, увы, я не понял.

Но есть простое решение - использовать другой класс, хорошо подходящий по своему функционалу - mx.effects.Pause:

<mx:Pause
id="somePause"
duration="2000"
effectEnd="somePause_effectEndHandler(event)"
/>

. . .

//Стартовать задержку
this.somePause.play();

. . .

private function somePause_effectEndHandler(event:EffectEvent):void {
//Обработать окончание задержки
}

среда, февраля 25, 2009

В цинковом гробу. Перетаскиваемые окошки

Волею судеб, свалился мне проект такой. Есть несколько флэшек, так называемых виджетов, которые нужно одеть в Zinc так, чтобы еще и под Mac OSX работали.

Во-первых, сразу зарекаюсь - Мак только для мак-девелоперов. Без меня. Такого количества проблем я уже давно не встречал. Возможно, основным виновником их является Zinc, который я смело могу назвать УСЛОВНО кросс-платформенным.

Что сказать про Zinc 3.0? Под красивым брендовым дизайном, симпатичной оболочкой, красивыми заголовками скрывается довольно ограниченный функционал, убогая документация и море непонятностей, глюков и граблей.

В данном посте, приведу один пример, как простая задача решается через "заднее место".
Нужно, чтобы окошко нашего виджета перетаскивалось мышкой за специальную панельку. В документации, нам рассказывают про это так: Creating a Draggable Form. И что мы получаем? Да полный отстой. Мышь теряет окошко, потом, при наведении вдруг опять подхватывается, уже без нашего на то соизволения, в общем, ужас. Как это победить? Нужно повесить 3 обработчика мыши на панельку и сделать это вот как:

dragNDropRenderer.buttonMode = true; dragNDropRenderer.useHandCursor = true;
dragNDropRenderer.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
dragNDropRenderer.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
dragNDropRenderer.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);

. . .

private function rollOverHandler(event:MouseEvent):void {
mdm.Forms.getFormByName("MainForm").startDrag();
}

private function rollOutHandler(event:MouseEvent):void {
if (!event.buttonDown) {
mdm.Forms.getFormByName("MainForm").stopDrag();
}
}

private function mouseUpHandler(event:MouseEvent):void {
var renderer:DisplayObject = DisplayObject(event.target);
if (!renderer.getBounds(renderer).contains(event.localX,event.localY))
mdm.Forms.getFormByName("MainForm").stopDrag();
}

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

Другие баги - почему под MacOX криво работает LocalConnection, или не открываются Zinc-ом новые окошки, и не распарсивается полученный с сервера XML, мне еще предстоит выяснить. Чувствую, это будут "приятные" сюрпризы.

* * *

В обработчик отпускания мыши добавлена проверка на отсутствие мыши в области панели.

* * *

Продолаются жалобы. Под MACOX не удалось (под Windows всё Ок) передать на сервер запрос с GET-параметрами (URLRequest). Запрос проходит, параметры не передаются. Не имел возможности выяснить, виновен ли в этом Zinc или админы сервера. В итоге, стали передавать параметры через POST, что сразу дало положительный результат.

* * *

Прозрачность. Плашка прозрачностью 1% ложится поверх поверхности со сложным изображением сложной прозрачности. Окно приложения устанавливается прозрачным. И что вы думаете? Эта плашка видна. Она как бы добавляет прозрачности подлежащему изображению. То же самое можно сказать, если поверх ложится растр с прозрачностью. Прозрачная область растра становится видна.
Выход - не допускать "недопрозрачностей", обтравливать растр во флэше.

* * *

Всё. Финиш. Zinc и MacOX - больше несовместимые понятия. Делаю полноэкранное приложение. В окне приложения, справа, где-то на 1/4 ширины, существует "мертвая" зона, в которой мышь перестает оказывать воздействие на интерактивные flash-элементы. Нет, нельзя сказать что совсем не оказывает. После 5-10 нажатий, кнопка срабатывает. Но это же бред. Элементраный пример - делаем во flash плашку размером с экран (1280x800), вставляем SWF в гроб, билдим и наблюдаем эту границу. Кошмар. Под Windows и под MacOX в Safari работает превосходно.
Сделать многооконное приложение с Zinc также не получилось - опять же проблемы с мышью. Интерактив не откликается.

понедельник, февраля 09, 2009

Прогресс-бар на любой вкус. Flex

Есть задачка, на первый взгляд, простая и, должно быть, хорошо изученная.
Сделать прогресс-бар (ProgressBar) совершенно не похожим на постепенно заполняющуюся горизонтальную полосу.

Скинирование позволяет заменить лишь изображения не залитой и залитой полос. Ну а если мне не нужна полоса?
Порыскав по интернету, пришел к выводу, что все усиленно заморачивались на проблему подмены предзагрузчика flash/flex-приложений, а вот видоизменить ProgressBar, почему-то никому не понадобилось.

Ну что ж, раз готового материала не нашлось, придется мастерить ручками.

Продолжение следует...

вторник, марта 18, 2008

Как открыть ссылку, заданную в htmlText компонента Text. Flex

Если задать HTML-текст как мы это делали всегда, ссылка станет активной, но открываться не будет:
<a href='http://www.adobe.com' target='_blank'>Go Home</a>

На лайф-доках есть статья, которая открывает нам этот новый секрет Flex. Теперь необходимо создавать обработчик, который будет осуществлять переход по ссылке:
<?xml version="1.0"?>
<!-- textcontrols/LabelControlLinkEvent.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" borderStyle="solid" backgroundGradientColors="[#FFFFFF, #FFFFFF]">
<mx:Script>
<![CDATA[
import flash.events.TextEvent;
public function linkHandler(event:TextEvent):void {
myTA.text="The link was clicked."; // Open the link in a new browser
window. navigateToURL(new URLRequest(event.text), '_blank')
} ]]>
</mx:Script>
<mx:Label selectable="true" link="linkHandler(event);">
<mx:htmlText>
<![CDATA[<a href='event:http://www.adobe.com'>Navigate to Adobe.com.</a>]]>
</mx:htmlText>
</mx:Label>
<mx:TextArea id="myTA"/>
</mx:Application>

Таким образом, мы сами контролируем открытие ссылок из текстовых блоков.

четверг, января 31, 2008

Видео во Flash/Flex. Проблемы позиционирования.

Задачу быстро сделать проигрыватель видео (управление видео-презентацией) я оценил в пару часов. Т.к. совсем недавно разобрался с воспроизведением высококачественного видео, с тех-частью проблем не должно было возникнуть. Проект начал делать на Flex, дабы лишний раз попрактиковаться.

Воспроизводить видео действительно получилось быстро. Класс VideoDisplay, управляемый несколькими кнопками и слайдером.
И тут встали более сложные задачи.
  1. Необходимо в определенные моменты времени останавливать видео (презентация).
  2. Небходима навигация по этим стоп-точкам.

Первая задача создала одну основную проблему: Получить видео-файл, содержащий сигнальные-точки (cue points).
Видео мы выгоняли из AfterEffects в MOV кодеком H.264. Можно ли туда загнать сигнальные-точки (которые, собственно были расставлены в тайм-лайне) и как это сделать - не смогли выяснить.
Решили экспортировать в FLV (задрав качество до порядка 3000) - расставить сигнальные точки пришлось вручную в "Adobe Flash CS3 Video Encoder". В принципе, была идея выгнать видео в MOV (высокое качество) и FLV (минимального качества), использовать сигнальные точки FLV а воспроизводить MOV.
Для получения сигнальных точек использую следующий код:
private function onMeta(event:MetadataEvent):void {
this.slider.maximum=event.info.duration;
this.__cue_points=event.info.cuePoints;
}
. . .
<mx:VideoDisplay metadataReceived="this.onMeta(event)" . . . >
. . .

Таким образом, по событию metadataReceived - когда Flex получает метаданные видео-файла - мы получаем массив сигнальных точек.
Внимание - свойство cuePoints класса VideoDisplay не будет содержать сигнальные точки, которые находятся в метаданных видео-файла. Это свойство нужно для "ручной" установки сигнальных точек. Управление (добавление/удаление) сигнальными точками cuePoints осуществляется менеджером сигнальных точек cuePointManager. Можно задать их прямо во Flex:
<mx:VideoDisplay . . . >
<mx:cuePointManagerClass>mx.controls.videoClasses.CuePointManager</mx:cuePointManagerClass>
<mx:cuePoints>
<mx:Array>
<mx:Object time="0" name="point1"/>
<mx:Object time="3.034" name="point2"/>
<mx:Object time="4.774" name="point3"/>
<mx:Object time="8.344" name="point4"/>
<mx:Object time="12.271" name="point5"/>
</mx:Array>
</mx:cuePoints>
</mx:VideoDisplay>

Итак, мы можем контролировать сигнальные точки. Переходим к обработке пауз на этих точках. Событие cuePoint отлично справляется с нашей задачей:
private function onCue(event:CuePointEvent):void {
this.video_display.pause();
}
<mx:VideoDisplay id="video_display" cuePoint="this.onCue(event)" . . . >

При обработке события сигнальной точки, воспроизведение видео останавливается четко в том месте, которое задает сигнальная точка. Это превосходно.

Задача номер два. А теперь начинается самое нехорошее. Мы имеем массив точек (каждый элемент содержит объект с двумя свойствами: name - имя маркера, time - время в секундах), и можем позиционировать воспроизведение видео по его элементам. Казалось бы, чего проще:
private function onClickNext(event:FlexEvent):void {
this.video_display.playheadTime=cue_points[position].time;
}

Ан нет. Видео позиционируется не точно в указанную позицию - то перескочет на пару секунд, то недотянет. Причем точность настолько низка, что нам пришлось отказаться от такого способа позиционирования.
По этому поводу, в документации Flex к свойству playheadTime сказано, что для FLV-файла позиционирование происходит в ключевой фрейм, ближайший к указанной позиции, причем эти ключевые фреймы формируются во время кодирования видео. Поэтому, извиняйте, но точно спозиционироваться в указанное место не получится, если там по близости нет ключевого фрейма. Попробовал позиционировать по тем же контрольным точкам MOV файл. Та же петрушка.
Эксперименты показали, что если видео экспортировать в SWF и позиционироваться по фреймам тайм-лайна, точность позиционирования абсолютна.

Раз нельзя реализовать нормальную навигацию по подгружаемому MOV/FLV видео, то дальнейшая разработка этого проекта на Flex потеряла всякий смысл.
Проще было импортировать видео в SWF, загнать его в мой старый, проверенный презентационный AS2 движок и обработать массив фреймов (составленный вручную за 15 минут), что и было сделано примерно за час.

Отрицательный результат - тоже результат. Потратив день на разборки, я узнал мгного нового и получил хороший опыт Flex-разработки.

понедельник, января 21, 2008

Как лучше постить код в Bloggere

Итак, выдрав код замены DIV на TEXTAREA отсюда, выявил несколько неудобств (копируемый в клипбоард код теряет переносы, необходимо заключать в дополнительный контейнер содержимое) и внес коррекции. Однако, остался один недостаток - теряются пробельные символы в начале строк. Кроме того, теряется форматирование, но, на мой взгляд, это не является большим минусом при выкладывании кода.

Итак, решение позволяет сделать так, чтобы код помещался в контейнере TextArea. Не более того.

Вот код преобразовывающего скрипта:

<script type="text/javascript">
// CodeBlocksSubstitutor
var i=0;
var j=0;
while(_DIV = document.getElementById("code"))
{ _DIV.id="processed";
if ((_DIV.innerText==null)(_DIV.innerText=="")) continue;
AREA = document.createElement("TEXTAREA");
AREA.id = "codeArea"+i;
if (_DIV.rows==null) AREA.rows = 10; else AREA.rows = _DIV.rows;
AREA.cols = 53;
AREA.readOnly = true;
AREA.wrap = "off";
i++;
AREA.innerText=_DIV.innerText;
newdiv=document.createElement("DIV");
newdiv.appendChild(AREA);
div_parent=_DIV.parentNode;
div_parent.replaceChild(newdiv,_DIV);
}
</script>


В тексте, код необходимо поместить в контейнер:

<div id="code" rows="20">
</div>

Параметр id="code" указывает на то, что текст необходимо обработать.
Параметр rows задает количество строк поля TextArea.
Тег div можно заменить на любой другой, например, code. Это повлияет на внешний вид контейнера.

Код я вставил в виде модуля HTML/JavaScript в нижний блок шаблона моего блога.

Пример:

package {
import flash.display.Sprite;
import flash.display.Bitmap;

[Frame(factoryClass="MyFactory")]
public class FrameTest extends Sprite
{
[Embed(source="big_asset.jpg")]
private var Asset:Class;

public function FrameTest()
{
init();
}

public function init():void
{
var asset:Bitmap = new Asset();
addChild(asset);
}
}
}

* * *

Обновил код: для пользователей альтернативных браузеров и Mac, текст в полях ввода не виден, всё из-за того, что на свойство innerText им совсем наплевать - оно не поддерживается DOM. Посему, не вдаваясь в подробности, я просто отключаю помещение кода в TextArea для всех браузеров, которые не IE. Возможно, позже найдется лучшее решение.
Да, знаю - камень в огород бесплатного блогирования.

пятница, января 18, 2008

Делаем прелоадер для Flex-приложения. AS3.

Если при разработке проекта нам доступен для редактирования таймлайн основного SWF, например, мы делаем проект во Flash IDE, всё просто - всё делаем как и раньше - а точнее - как нам советует в своей статье "Экспорт классов во второй кадр и создание прелоадера во Flash CS3" __etc.
А что делать, если наш проект компилируется Flex SDK?
Можно сделать маленький модулек, который будет загружать и мониторить загрузку основного SWF. Ну а если требуется наличие только одного SWF?

Люди советуют почитать статью Preloaders in AS3. Читаем.

Основную мысль автору статьи, подсказал Ted Patrick, намекнув на мета-тег [Frame] и поглядеть исходник mx.core.Application.
Поглядим-ка
"...\Flex2SDK\frameworks\source\mx\core\Application.as ".
Как отметил 101 (тот что автор статьи) там и правда есть тег [Frame(factoryClass="mx.managers.SystemManager")]. А в комментарии, по-моему, ключевой является фраза "Все фреймворки инициализируются SystemManager-ом".

Идем смотреть
"...\Flex2SDK\frameworks\source\mx\managers\SystemManager.as".
И правда - видим интересные фразы типа "ВНИМАНИЕ: Минимизируйте не флэшовые классы, которые импортируете здесь, всё что связано с SystemManager будет загружено в 1й фрейм до того, как загрузится прелоадер, и вообще, что-либо отображающееся." Кроме того, несколько ниже, говорится, что "SystemManager - первый визуальный класс, который создается в приложении. Он так же отвечает за создание mx.preloaders.Preloader, который отображает mx.preloaders.DownloadProgressBar до конца загрузки приложения, после чего SystemManager создает mx.core.Application instance". Собственно, вызывается метод SystemManager.create, код которого приводит 101 (автор).
Он пришел к следующим мыслям:
  • Сначала создаем основной класс MainClass как обычно и указываем компилятору чтобы он его компилил.
  • Затем в этом классе вставляем тег [Frame(factoryClass="MyFactoryClass")], который указывает на некий другой класс MyFactoryClass.
Это должно привести к тому, что скомпилируется SWF с двумя фреймами! Всё барахло, которое мы имбедим, наш основной класс, другие классы которые он пользует - всё это будет импортироваться во второй фрейм. Единственное, что будет импортировано в первый фрейм - наш класс MyFactoryClass и всё что он пользует. Шикарно!

Итак, нам остается всего-навсего создать класс обычного прелоадера, который:
  • Делает stop();
  • Мониторит загрузку любым удобным для нас способом.
  • После полной загрузки делает nextFrame();
Теперь мы можем инстанцировать основной класс используя getDefinitionByName() {А откуда?}. Это дает нам возможность контролировать, какой класс мы хотим сделать основным. Кроме того, теперь мы можем выгрузить прелоадер.
Еще одна любопытная особенность этого решения - основной таймлайн представляет MainClass, но в качестве "Document Class" теперь выступает не MainClass, а MyFactoryClass. Из этого следует:
  • MyFactoryClass должен наследоваться от MovieClip. И не в коем случае не от Sprite.
  • При инстанцировании MainClass, необходимо добавить (addChild) его в дисплей-лист MyFactoryClass.
  • MainClass не будет являться корнем дисплей-листа. Он будет чайлдом MyFactoryClass.
  • В своем конструкторе, MainClass не должен ссылаться на "stage", так как он будет доступен только после добавления (addChild) MainClass в дисплей-лист.
Теперь, всё, что осталось для нас неясным, развеем примером: код примера.

В основном классе FrameTest - это то что выше называлось MainClass - всё просто. Имбедится и выводится картинка "big_asset.jpg", желательно очень большого размера. Единственное необычное - это фраза [Frame(factoryClass="MyFactory")].

Класс MyFactory - это наш вышеописываемый MyFactoryClass.
  • В конструкторе производится остановка тайм-лайна stop(), выставляются параметры stage и добавляется обработчик "ENTER_FRAME".
  • Обработчик onEnterFrame() рисует полосу состояния загрузки вычисляя процент загрузки: var percent:Number = root.loaderInfo.bytesLoaded / root.loaderInfo.bytesTotal;
  • При выполнении условия framesLoaded == totalFrames, объект отписывается от события "ENTER_FRAME", осуществляет переход на следующий фрейм nextFrame() и производит инициализацию init().
  • Метод инициализации init() получает определение основного класса var mainClass:Class = Class(getDefinitionByName("FrameTest")); и, если такой класс существует if (mainClass), инстанцирует его и добавляет в дисплей-лист: var app:Object = new mainClass(); addChild(app as DisplayObject);.

Всё. Переходим к практике.

* * *

Не забудем положить картинку "big_asset.jpg" в папку с классами.

Первая коррекция - getDefinitionByName вызывает исключение, в случае если класс не найден. Поэтому проверки if(mainClass) недостаточно. Нужна обработка исключения try ... catch.

* * *

Пробуем trace(this.currentFrame);. Он выдает правильно - 1 из конструктора MyFactory, 2 - из init();.

Попробуем, как это будет работать в интернете. Хм. Прелоадер отрабатывает, но как-то поздно. Мой Naviscope показывает, что SWF загружается больше чем на половину, когда только начинает происходить отрисовка полосы загрузки. Попробую еще утяжелить SWF-ку. Для этого добавляю картинок.

Интересное наблюдение - если накопировать одну и ту же картинку и имбедить копии, размер SWF не изменится - как будто внедрена одна картинка! Вот это сжатие!

Итак, утяжелил до 20 мБ. Теперь всё встало на свои места. Прелоадер аккуратно отрабатывает объем и затем отображается картинка! Всё дело было в слишком быстром интернете.

Итак, подход прост и практичен. Спокойно делаем правильные и эффектные флэшки любого размера!

воскресенье, ноября 25, 2007

Загружаемый растр. Как включить сглаживание при трансформациях. AS2

Я не нашел штатных средств Flash, которые бы позволили сделать сглаживание для загруженного (через MovieClipLoader) растрового изображения.
Решил обойти эту проблему, используя класс BitmapData. Код здесь.

пятница, ноября 23, 2007

Паттерн Singleton в языке ActionScript

Наконец решил использовать Singleton явно и в полную силу.
С удивлением обнаружил что раньше не вставил ссылку на эту статью в свой блог и теперь потратил время чтобы перерыть flash-ripper в поисках ссылки...
Итак, как резюме - здесь пример паттерна на AS3, хотя никто нам не мешает модифицировать и использовать этот код для AS2 (правда уже не получится реализовать такой же запрет на инстанцирование через конструктор).

* * *

Запрет на инстанцирование на AS2 делается еще проще чем на AS3, так как есть возможность объявить конструктор класса как private.

понедельник, ноября 19, 2007

Видео с камеры

var webcam:Camera = Camera.get();
cam_video.attachVideo(webcam);

где cam_video: компонент Video.

суббота, ноября 17, 2007

Об особенностях мониторинга загрузки, об экспорте для AS и об импорте классов. AS2

Важно знать:
  1. Если клип экспортируется для ActionScript посредством Linkage > Export for ActionScript, при отмеченном параметре Export in first frame, этот клип будет доступен для "attachMovie" с первого же фрейма, но будет помехой для правильного мониторинга загрузки SWF-файла, т.к. первый фрейм не будет выведен до тех пор, пока все его клипы не загрузятся. При этом, загрузка некоторого (довольно приличного) объема данных не будет отображена, что не есть хорошо.
    Для того, чтобы отложить загрузку такого клипа, необходимо снять параметр Export in first frame. Однако если явным образом такой клип не присутствует во временной шкале, он не будет экспортирован в SWF вообще. Поэтому, для экспорта таких клипов нужно отвести какой-нибудь фрейм, который никогда не будет показан при воспроизведении SWF.
  2. Классы из Publish settings > Flash > Settings > Classpath и классы из текущего каталога импортируются во фрейм, указанный там же, в Export frame for classes. Для идеального мониторинга загрузки, лучше указать не 1-й фрейм, а какой-либо другой, располагающийся после модуля мониторинга загрузки .
    Странно, но классы, импортируемые "вручную" также не могут быть использованы до этого фрейма.
  3. Если с клипом ассоциирован класс по средством параметра Linkage > Export for ActionScript, и для клипа и для класса всё происходит как в 1-м и 2-м пунктах.

Особенности мониторинга загрузки (preloader):

  1. Модуль мониторинга загрузки должен располагаться до фрейма, в который импортируются классы и экспортируются клипы.
  2. Мониторинг не может быть описан классом.
  3. Модуль мониторинга загрузки должен иметь минимальный объем.
  4. При подсчете процента загрузки SWF, необходимо учитывать объем уже загруженных на момент активации мониторинга данных:

    На момент инициализации мониторинга:
    this.skipped=_root.getBytesLoaded();
    this.total=_root.getBytesTotal()-this.skipped;

    В процессе подсчета загруженного объема:
    var progress:Number=(_root.getBytesLoaded()-skipped)*100)/this.total;

Код подключаемого кода здесь.

воскресенье, ноября 11, 2007

Delegate. Проблема доступа к вызывающему объекту

this.item.area.onRelease=Delegate.create(this,this.onItemRelease);

Объектов item может быть много. Необходимо в onItemRelease как-то добраться до area, которое вызвало событие.

Неполучилось.

Есть конечно способы модифицирующие класс Delegate, но хотелось бы без этого.

* * *

Обсудили этот вопрос. Наиболее изящным мне показался следующий метод:

Для Area определяем:

var onReleaseWithThis:Function;
function onRelease() {
onReleaseWithThis(this);
}

Теперь для главного класса:

this.item.area.onReleaseWithThis=Delegate.create(this,this.onItemRelease);
function onItemRelease(who) {
trace(who);
}

* * *

В итоге, склонился к методу перекрытия класса Delegate своим, с передачей параметров. Использовать удобно, подключать удобно. Разве что неудобно таскать из проекта в проект.

Заметил правда один хак, который сам непонимаю почему работает. При передаче дополнительных параметров при create, они находятся в области видимости create, но затем, почему-то легко доступны в самой вызываемой функции уже позже, при работе программы. А нет ли такой вероятности, что эти параметры удалятся тем же Garbage Collector ом? Тем не менее метод работает, и я его буду использовать. Благо в AS3 такой ерундой заниматься уже нет необходимости.

четверг, ноября 01, 2007

Как загрузить библиотеку и затем аттачить из нее клипы

Встал вопрос, как это сделать. Нашел такой код. Надо пробовать.

* * *

Попробовал, работает превосходно. Обожаю AS3.

* * *

Трансформируя вышеприведенный код получаем очень простое решение:

Перед загрузкой указываем лоадеру контекст:
var context:LoaderContext = new LoaderContext(true, ApplicationDomain.currentDomain);
this.loader.load(this.source_url, context);

Затем, уже после того как загрузится swf-ка, мы в любой момент можем сделать следующее:

var movie_class:Class = ApplicationDomain.currentDomain.getDefinition("MovieClass") as Class;
var movie_sprite:Sprite = new movie_class();
this.addChild(movie_sprite);

Как загрузить библиотеку и затем аттачить из нее клипы

Встал вопрос, как это сделать. Нашел такой код. Надо пробовать.

Версия подгружаемой SWF

Смотреть 4й байт. Код.

среда, октября 31, 2007

Странно: значения параметров функции по умолчанию не могут быть public static const. AS3

Есть такой метод:

public function TKeyboardSettings(left:int=Keyboard.LEFT,right:int=Keyboard.RIGHT,up:int=Keyboard.UP,down:int=Keyboard.DOWN) {
this.left=left;
this.right=right;
this.up=up;
this.down=down;
super();
}


На Flex Builder 3 beta1 всё было ок, но после установки второй беты и (как я потом проверил, во FlashDevelop) flex стал ругаться на то, что я параметрам по умолчанию присваиваю константы класса Keyboard.

Текст ошибки:
Parameter initializer unknown or is not a compile-time constant.

Судя по сообщению, константы класса Keyboard не являются константами времени компиляции.
Непонятно, почему до последнего времени это не являлось ошибкой.

* * *

Долго ковырялся - в FD заработало ни с того ни с сего. В FB вдруг в процессе редактирования выдало Source could not be found for flash.ui.Keyboard.RIGHT in ...\playerglobal.swc
Выходит криво встал билдер то...

* * *

Переустановил. То же самое и в FD опять началось... :(

среда, сентября 26, 2007

Настройка нормального хелпа под FlashDevelop IV

Код прилагается: здесь.

В процессе изучения выяснилось, что приложение с параметрами из FlashDevelop запускается следующим образом: "app.exe;param1 param2 param3".

В настройках тулбара я прописал строку:
<button label="Help" tag="C:\Program Files\FlashDevelop\AsLocalDocs\ASLocalDocs.exe;pckg=$(ItmTypPkg) clss=$(ItmTypName) item=$(ItmName) kind=$(ItmKind)" image="229" click="RunProcess"/>

и на F1 в настройках плагина прописал строку:
C:\Program Files\FlashDevelop\AsLocalDocs\ASLocalDocs.exe;pckg=$(ItmTypPkg) clss=$(ItmTypName) item=$(ItmName) kind=$(ItmKind)

Осталось добиться, чтобы приложение ASLocalDocs.exe запускалось в одном экземпляре.
Еще - надо избежать ошибок, если не найден html-файл.
Кроме того, сам плагин дает сбой, либо не реагирует при вызове не классов.

вторник, сентября 25, 2007

Еще раз о Delegate. AS2

Никак не запомню...

import mx.utils.Delegate;
obj1={name:"name1"};
obj2={name:"name2"};
obj1.test="Test";
obj2.function_name2=function() { trace("Result: "+this.test+" "+this.name);}
obj1.function_name1=Delegate.create(obj1,obj2.function_name2);
obj1.function_name1();

Результат: Result: Test name1

obj1 - Контекст или объект для которого делегируется функция.
obj2 - Объект, который поручает свой метод.
obj1.function_name1 - функция, которой поручается выполнение.
obj2.function_name2 - поручаемая функция.

Пример применения.
Кнопка button вызывает по нажатию метод, делегированный объекту-родителю:

import mx.utils.Delegate;
this.button.onRelease=Delegate.create(this,
function() {
this.doSomething();
}
);

вторник, сентября 11, 2007

Как сделать, чтобы в текстовом поле по клавише TAB вводился TAB а не сменялся фокус

Пример, как сделать, чтобы в текстовом поле по клавише TAB вводился TAB а не сменялся фокус.

<?xml version="1.0" encoding="utf-8"?>
<!-- TextAreaTabAllowed -->
<mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Script>
<![CDATA[
private var _allowTabKey:Boolean = false;
[Bindable]

public function set allowTabKey ( value:Boolean ) : void
{
if( value )
{
addEventListener( FocusEvent.KEY_FOCUS_CHANGE,
catchTabKey);
}
else
{
removeEventListener( FocusEvent.KEY_FOCUS_CHANGE, catchTabKey);
}
_allowTabKey = value;
}

public function get allowTabKey ( ) : Boolean
{
return _allowTabKey;
}

private function catchTabKey ( e:FocusEvent = null ) :
void
{
if( e )
{
var before:String = this.text.substring ( 0,
this.selectionBeginIndex );
var after:String =
this.text.substring( this.selectionEndIndex,
this.text.length );
var newCaretPos:int = this.selectionBeginIndex +
1;
this.text = before + "\t" + after;
this.setSelection( newCaretPos, newCaretPos );
e.preventDefault( );
this.setFocus ( );
}
}

]]>

</mx:Script>
</mx:TextArea>