barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)
Показаны сообщения с ярлыком ActionScript. Показать все сообщения
Показаны сообщения с ярлыком ActionScript. Показать все сообщения

понедельник, 21 января 2013 г.

away3d 4.0: ObjectContainer3D и mouseEnabled

Установка у объекта ObjectContainer3D свойства mouseEnabled к сожалению не дает никакого эффекта: контейнер по-прежнему не может принимать события MouseEvent3D. Поэтому навешивать обработчики событий MouseEvent3D надо не на сам контейнер, а на его потомков (если они сами не являются контейнерами). Для этого, например, можно переопределить метод ObjectContainer3D.addEventListener() так:
override public function addEventListener(
type : String,
listener : Function,
useCapture : Boolean = false,
priority : int = 0,
useWeakReference : Boolean = false) : void
{
if(type == MouseEvent3D.CLICK
|| type == MouseEvent3D.DOUBLE_CLICK
|| type == MouseEvent3D.MOUSE_DOWN
|| type == MouseEvent3D.MOUSE_MOVE
|| type == MouseEvent3D.MOUSE_OUT
|| type == MouseEvent3D.MOUSE_OVER
|| type == MouseEvent3D.MOUSE_UP
|| type == MouseEvent3D.MOUSE_WHEEL
)
for(var i:uint=0;i<this.numChildren;i++)
{
var child:ObjectContainer3D = this.getChildAt(i);
child.addEventListener(
type,
listener,
useCapture,
priority,
useWeakReference
);
}
}
У потомков при этом, естественно, должно быть установлено свойство  mouseEnabled = true.

четверг, 3 января 2013 г.

Использование fl.controls.* в Flash Builder - проекте

Задача:

Использовать в ActionScript-проекте во Flash Builder компоненты из пакета fl.controls.

Решение:

Сначала необходимо создать swc-библиотеку с нужными компонентами (для этого понадобится Flash Professional), а затем подключить её к Flash Builder-проекту.
Чтобы сделать первое, нужно:
1) Создать fla-проект в Flash Professional
2) Перетащить нужные компоненты из окна "Компоненты" в окно "Библиотека":
3) Экспортировать SWC. Для этого щелкнуть правой кнопкой мыши по любому из компонентов, перетащенных в библиотеку, и выбрать соотв. пункт меню:
4) Всё, теперь, когда создан SWC-файл, можно добавлять его путь сборки Flash Builder-проекта:

среда, 7 ноября 2012 г.

away3d 4: 3D-модели, экспортируемые из Prefab3D, и утечка памяти

Полчаса размышлений, и источник утечки памяти, возникающей при пересоздании 3D-объектов, экспортированных из Prefab3D (версия - 2.124), найден. В классе ASBase, являющимся базовым для всех экспортируемых 3D-моделей, отсутствует корректное переопределение метода dispose(), очищающее занимаемые ресурсы. Переопределив метод так:

public override function dispose():void
{
super.dispose();
var i:uint;
for(i=0;i<_meshes.length;i++)
_meshes[i].dispose();
_meshes=null;
for(i=0;i<_containers.length;i++)
_containers[i].dispose();
_containers=null;  
for(i=0;i<_materials.length;i++)
_materials[i].dispose();
_materials=null;
}  
мы избавляемся от утечки памяти.

пятница, 2 ноября 2012 г.

away3d 4.0: view.camera.project() и инициализация сцены

Столкнулся с непонятной для меня особенностью away3d 4.0: если использовать метод  view.camera.project() для проецирования 3D-точки в 2D-плоскость экрана в конструкторе основного спрайта флешки, или же в обработчике его события Event.ADDED_TO_STAGE, проецирование выполняется неверно (по крайней мере, оно не совпадает с последующими попытками спроецировать ту же точку). Тоже поведение наблюдается и при использовании метода в обработчике Event.ENTER_FRAME при его первых 3-4 срабатываниях. 
Описанное выше поведение я замечаю при использовании линзы OrthographicLens, а ошибка проецирования заключается в сжатии проекции по оси Ox.
Как оказалось, на линзе возникает событие LensEvent.MATRIX_CHANGED, до которого проецирование неверное, а после которого становится верным. Поэтому, если после инициализации флешки есть необходимость спроецировать какую-либо 3d-точку с использованием камеры, нужно дождаться сначала срабатывания события LensEvent.MATRIX_CHANGED.

среда, 24 октября 2012 г.

away3d: скриншоты, или как отрисовать View3D на Bitmap

В away3d 4.0 делать скриншоты содержимого флешки простым:
myBitmap.draw(flashSprite);
не получится (здесь myBitmap - это объект BitmapData, в который запишется скриншот, а flashSprite - корневой спрайт флешки). Выходит это по той причине, что Stage3D не принадлежит списку отрисовки, и в битмапе мы получим все, кроме 3D-контента.
Однако, есть способ получить в битмап содержимое 3D-вида (объекта View3D):
_view.renderer.swapBackBuffer = false;
_view.render();
_view.stage3DProxy.context3D.drawToBitmapData(myBitmap);
_view.renderer.swapBackBuffer = true;
Хитро, но работает, спасибо форуму away3d: http://away3d.com/forum/viewthread/1960/.

среда, 3 октября 2012 г.

away3d: двусторонний материал и освещение

Установив у материала свойство bothSides=true, можно добиться, чтобы обе стороны граней, на которые материал наложен, были видимыми (в противном случае одна будет видимой, другая - прозрачной). Однако, если к материалу применено освещение (установлено свойство lightPicker), вторая сторона будет некорректно вести себя по отношению к свету. Т.е., например, если освещение падает только со стороны наблюдателя, одна сторона грани будет корректно освещена, в вот вторая будет казаться неосвещенной.
Дело в том, что освещение грани рассчитывается исходя из угла между нормалью к ней и направлением света. При этом нормаль у грани одна на обе стороны, и для одной стороны она оказывается "выходящей" навстречу наблюдателю, и, значит, освещению, а для второй - "входящей", сонаправленной с направлением света.
Варианта выхода из данной ситуации 2: либо научить away3d самостоятельно инвертировать нормаль при расчете освещенности обратной стороны, либо дублировать все грани фигуры, разворачивая их нормали в обратную сторону. Последнее делается просто, воспользовавшись away3d.tools.helpers.MeshHelper`ом:
var mesh:Mesh = new Mesh(geometry, material);
var duplicateMesh =  new Mesh( geometry.clone(), material);
MeshHelper.invertFaces(duplicateMesh);
Первый вариант сложнее, я пока не копал в эту сторону, хотя с целью уменьшения числа граней и экономии ОП, пожалуй, стоит попробовать. 

пятница, 21 сентября 2012 г.

away3d 4: виджет статистики

Раньше (в away3d 3.5) виджет статистики не требовал программного добавления и был доступен в контекстном меню при клике на 3D-объекте. Теперь он добавляется программно:
import away3d.Away3D;
...
addChild(AwayStats.instance);
Как и раньше, он содержит сведения о FPS, использовании памяти и пр.:


Чтобы увидеть статистику по числу полигонов и драйверу, необходимо зарегистрировать все используемые View3D (у меня, например, из два):
AwayStats.instance.registerView(_leftView);
AwayStats.instance.registerView(_rightView);
Теперь статистика выглядит так:


суббота, 15 сентября 2012 г.

Проект away3d 4.0 в Flash Builder 4.6: пустой экран и ошибка "Класс Context3D недоступен"

Проблема:

Создал ActionScript-проект в Flash Builder 4.6, подключил сорцы away3d 4.0, но при запуске даже элементарных примеров с away3d.com получаю пустой экран и ошибку (если установлен отладочный Flash Player):
Error #2044: Необработанный ErrorEvent:. text=Error #3702: Класс Context3D недоступен.
Решение:

Открыть html-шаблон, который используется для запуска проекта, и установить в нем параметр wmode равным "direct" в JavaScript-коде создания swf-объекта:

<script type="text/javascript">
            // For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
            var swfVersionStr = "${version_major}.${version_minor}.${version_revision}";
            // To use express install, set to playerProductInstall.swf, otherwise the empty string.
            var xiSwfUrlStr = "${expressInstallSwf}";
            var flashvars = {};
            var params = {wmode: "direct"};
            params.quality = "high";
            params.bgcolor = "${bgcolor}";
            params.allowscriptaccess = "sameDomain";
            params.allowfullscreen = "true";
            var attributes = {};
            attributes.id = "${application}";
            attributes.name = "${application}";
            attributes.align = "middle";
            swfobject.embedSWF(
                "${swf}.swf", "flashContent",
                "${width}", "${height}",
                swfVersionStr, xiSwfUrlStr,
                flashvars, params, attributes);
            // JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
            swfobject.createCSS("#flashContent", "display:block;text-align:left;");
        </script>
Это включит аппаратное 3D-ускорение. Предыдущие версии библиотеки работали с другими wmode`ами (transparent, opaque), что, конечно, давало проигрыш в производительности, но всё же. У wmode=direct есть одна особенность: объекты View3D всегда располагаются под остальным 2D-контентом, независимо от порядка их добавления в контейнер вызовом addChild и от индекса при добавлении с помощью addChildAt. Так что нужно быть осторожным, чтобы, например, случайно не залить 3d-сцену поверх как-нибудь заливкой.

четверг, 7 июля 2011 г.

Редактор с подсветкой синтаскиса ActionScript под Linux

От одной только подсветки синтаксиса толку конечно мало, но бывает нужна именно она (просто посмотреть какой-нибудь файлик). Нашел замечательную вещь - Geany (в репозитории Debian присутствует) - не просто подсвечивает синтаксис, но вообще является IDE (компиляторов правда он не включает, их нужно подключать отдельно). Т.е. для того же ActionScript он показывает классы, методы и члены класса (намешал правда все в кучу - и члены класса, и локальные переменные в методах, так что не очень юзабельно).

пятница, 1 апреля 2011 г.

Рисование дуги окружности в ActionScript

Встроенных средст рисования дуг в ActionScript нет, поэтому пришлось написать свою функцию:

protected function drawArc(gr:Graphics,centerX:Number,centerY:Number,R:Number, startAngle:Number, endAngle:Number, angleStep:Number=1):void
        {
            var xc : Number, yc : Number;
            xc = centerX+R*Math.sin(startAngle*Math.PI/180);
            yc = centerY-R*Math.cos(startAngle*Math.PI/180);
            gr.moveTo(xc,yc);
            for (var i:Number=startAngle+angleStep; i<=endAngle; i+=angleStep)
                {
                xc = centerX+R*Math.sin(i*Math.PI/180);
                yc = centerY-R*Math.cos(i*Math.PI/180);
                gr.lineTo(xc,yc);
                }
        }

Форматирование отображения чисел с плавающей точкой в ActonScript

Не нашел я в ActionScript аналога С-шного / php-шного sprintf для того, чтобы задать параметры отображения числа с плавающей точкой (Number) при преобразовании в строку.. Зато у Number есть метод Number.toFixed(p), преобразующий его в число с фиксированной запятой, где p - число разрядов после запятой.

urlencode / urldecode в ActionScript

Функции ActionScript, аналогичные вышеуказанным - escape() и unescape().

Аналог php`шного var_dump() для Flash / ActionScript

Нашел очень полезную функцию для получения дампа любых объектов в ActionScript, типа var_dump() в php. Используется она очень просто:

import com.flexer.Debug;

...

Debug.dump(someObj) ;

Сам класс можно скачать тут: http://www.flexer.info/2008/06/25/dump-debug-method-like-var_dump-function-in-php-and-debug-class/ или тут: http://narod.ru/disk/360902001/var_dump_sources.zip.html