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

SmartFoxServer. Конфигурация зон.

Конфигурация зон располагается в контейнерном теге <Zones/>. Каждая зона представлена тегом <Zone/> в Config.xml Этот файл располагается в директории сервера (для Windows это "C:\Program Files\SmartFoxServerPRO_1.6.0\Server\").

Параметры зоны:
name - имя зоны
uCountUpdate - Вкл/выкл (true/false) посылку сервером сообщений о количестве пользователей. Это необходимо для мониторинга в реальном времени статуса комнат.
ВАЖНО: Необходимо определиться - использовать ли глобальное обновление статуса комнат или нет. К примеру, если в списке комнат необходимо отображать текущее количество пользователей и обновлять его в реальном времени, этот параметр необходим. Если же требуется сократить объем трафика, то лучше обновление производить по запросу (кнопка "Обновить"), а этот параметр отключить. Для игровых комнат по умолчанию равен "false".
maxUsers - максимальное число пользователей, которым доступна зона.
maxRooms - максимальное число комнат в зоне, которое могут создать пользователи. Без ограничения равно -1.
maxRoomsPerUser - максимальное число комнат, которое может создать пользователь за один сеанс. По умолчанию равно 5.
emptyNames - Вкл/выкл (true/false) возможность анонимного входа. Если параметр включен, и пользователь входит анонимно, ему присваивается имя "Guest_"+номер.
roomListVars - Если "true", то при запросе списка комнат сервер будет выдавать все переменные каждой из комнат.
BuddyList - список друзей. Устаревший параметр - не будем его пользовать. В новых версиях список задается во вложенном теге <BuddyList/> .

Зона может содержать следующие теги:
<Moderators/> - список модераторов. Это контейнер, содержащий список тегов <Mod/>, с двумя параметрами: name и pwd - имя и пароль модератора.

<DisabledSysEvents/>, список событий сервера, которые необходимо блокировать. Это контейнер, содержащий список тегов <event/> заключающих в себя название события.

<DisabledSysActions/>, список действий сервера, которые необходимо блокировать. Это контейнер, содержащий список тегов <action/> заключающих в себя название действия.

<UserNameAvoidChars/> - запрещенные символы в именах пользователей. Указываются в виде строки, заключенной в CDATA.
<RoomNameAvoidChars/> - запрещенные символы в именах комнат. Указываются в виде строки, заключенной в CDATA.
<MaxUserNamesLen/> - максимальное число символов в именах пользователей.
<MaxRoomNamesLen/> - максимальное число символов в именах комнат.

<AutoReloadExtensions/> - разрешает немедленное обновление серверных скриптов после их модификации.

Ниже рассмотрены другие теги, которые включены в зону.

Параметры списка друзей
Тег <BuddyList/> определяет конфигурацию списка друзей.
Параметр active включает активность списка.

Базовые параметры:
<mode/> - режим работы: basic (поддерживает совместимость со старыми версиями) и advanced (позволяет использовать новые возможности).
<size/> - максимальное число пользователей.
<maxBuddyVars/> - максимальное число переменных на каждого друга.

Новые параметры:
<addBuddyPermission/>, <permissionTimeOut/>, <mutualAddBuddy/>, <mutualRemoveBuddy/> -параметры взаимодействия пользователей в списках друзей.
<offLineBuddyVariables/> позволяет включить режим передачи запросов off-line пользователю с ожиданием, когда он выйдет в on-line.
<persisterClass/> - позволяет указать имя другого класса для обработки списков друзей.

Параметры конфигурации комнат.
name - имя комнаты
isPrivate - требует пароль для входа
pwd - пароль для входа в комнату
isGame - включает дополнительные функции, необходимые для игрового сервера.
limbo - Специальная комната, которая может содержать тысячи не взаимодействующих посетителей. Такие комнаты не генерируют определенных событий, не позволяют рассылать массовые сообщения и т.п.
maxUsers - максимум пользователей, которые могут одновременно присоединиться к комнате. Рекомендуется от 2 до 50 пользователей.
maxSpectators - максимум наблюдателей.
autoJoin - по команде клиента autoJoin(), пользователь по-умолчанию войдет в эту комнату.
uCountUpdate - аналогично одноименному параметру зоны. Для игр лучше установить "false".

Переменные по умолчанию
<Vars/> содержит список тегов <Var/>, в который контейнерно заключается значение переменной. Каждый из тегов содержит параметры переменной:
name - имя переменной.
type - тип переменной ( s = string, n = number, b = boolean ).
private - если true, переменная является приватной.

Серверные скрипты (или расширения)
<Extensions/> содержит список тегов <extension/>.
Каждый из тегов содержит параметры скрипта:
name - имя скрипта.
className - имя файла скрипта.
type - "script" для ActionScript, "python" для Python, "java" для Java.

Другие параметры.
Были замечены другие параметры.

Для Zone:
customLogin

Для Room
isTemp

Их значение выясним позже.

Настраиваем SmartFoxServer

Панель управления SmartFoxServer предоставляет довольно богатый набор возможностей.

Для начала заменим пароль администратора сервера. По умолчанию это sfs_admin/sfs_pass, что не очень удобно вводить при старте. Да и сообщение с просьбой сменить пароль надоедает быстро. Идем в раздел Config.xml и находим строку <!-- Adminisitrator login -->. Меняем логин и пароль на более удобные для нас. Пароль должен быть не меньше 6ти символов. Для того, чтобы изменения вступили в силу необходимо рестартовать сервер.

В разделе панели Zone Browser можно просмотреть состояние зон. По умолчанию, на сервере уже создано много зон под разные нужды - в основном для работы примеров.

Чтобы добавить свою зону нам необходимо опять вернуться к Config.xml.
Конфигурацию зон мы рассмотрим в следующем посте.

Попробуем дублировать тег Zone для simpleChat. Переименуем имя, установим параметры.
Теперь в разделе Zone Browser появилась наша зона и мы можем просмотреть ее комнаты и параметры.

Теперь дело за клиентской частью.

Инструмент для администрирования SmartFoxServer

В поставке SmartFoxServer инструмент для администрирования в виде SWF-файла. Если попытаться воспользоваться им локально, локальная политика безопасности Flash Player не даст подключиться к серверу.
Чтобы избежать этой проблемы, я нашел два средства:
  1. Плохой способ - cделал загрузчик с loadMovie, который грузит AdminTool.swf в рут. Из-под FlashIDE можно спокойно запускать.

  2. Конечно же самый лучший способ - убрал SWF в Zinc. Облагородил его красочным скином и сделал EXE-файл.

Теперь можно комфортно администрировать сервер.

DisplayObjectWrapper от G.Skinnerа. Flex

Как сделать, чтобы такие ассеты как Flash-символы или изображения были совместимы с Flex-компонентами? Грант Скиннер (Grant Skinner) предлагает свой способ: "обернуть" ассет в объект UIComponent, который будет транслировать API трансформирования Flex в API трансформации Flash-объектов DisplayObject.
Класс "обертки" можно взять здесь.
Пимер использования в MXML:
// mxml, syntax 1:
<local:DisplayObjectWrapper>
<DisplayObjectToWrap/>
</local:DisplayObjectWrapper>
// mxml, syntax 2:
<local:DisplayObjectWrapper content="com.gskinner.MyClass"/>
// where content is either a qualified class name as a string
// mxml, synax 3:
<local:DisplayObjectWrapper content="{ myInstance }"/>

Пример использования в ActionScript:
// in a script block (ex. in an initialization handler):
var dow:DisplayObjectWrapper = new DisplayObjectWrapper();
dow.content = new Sprite(); // or any DisplayObject instance
myContainer.addChild(dow);

Видео во 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-разработки.

вторник, января 29, 2008

Тег [Bindable]. Flex

Если нам необходимо связать два свойства так, чтобы при изменении первого (источника) Flex автоматически копировал данные во второе (приемник), мы можем использовать метатег [Bindable]. Указав [Bindable] перед свойством-источником, мы даем понять Flex, что при изменении свойства надо генерировать событие.
[Bindable]
[Bindable(event="eventname")]

Если событие не указано явно, то по умолчанию создается событие propertyChange.

Тег [Bindable] используется в трех случаях:

  1. Перед определением класса. В этом случае, для всех (только!) public свойств (и переменных, и установщиков) Flex автоматически генерирует событие propertyChange типа PropertyChangeEvent, и все эти свойства могут использоваться как источники связывания данных.
    [Bindable]
    public class TextAreaFontControl extends TextArea {}
  2. Перед public, protected, private свойствами, определенными как переменные.
    При изменении свойств, Flex автоматически генерирует событие propertyChange типа PropertyChangeEvent. Можно также указать другое имя события.
    [Bindable(event="fooChanged")]
    public var foo:String;
  3. Перед public, protected, private свойствами, определенными как установщики. Для того, чтобы свойство являлось источником связывания данных, необходимо чтобы были определены и set, и get методы.
    Если указан только set метод, создается свойство "только для записи" и его нельзя использовать в качестве источника связывания данных.
    Если же указан только get метод, создается свойство "только для чтения", которое можно использовать как источник связывания данных и без вставки метатега - аналогично переменным, определеных как const.
    При изменении свойств, Flex автоматически генерирует событие propertyChange типа PropertyChangeEvent. Можно также указать другое имя события.
    [Bindable]
    public function set shortNames(val:Boolean):void { ... }
    public function get shortNames():Boolean { ... }

ВАЖНО: Если после изменения, свойство не приобрело новое значение, Flex не генерирует событие. Проверка осуществляется по принципу (oldValue !== value).

ВАЖНО: Если свойство содержит ссылку на объект и эта ссылка заменяется на другую, то событие генерируется. Если же изменяется объект, на который ссылается свойство, событие генерироваться не будет.

Свойства read-only и static по-умолчанию являются источниками связывания данных.

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

// Define private variable.
private var _maxFontSize:Number = 15;

[Bindable(event="maxFontSizeChanged")]
// Define public getter method.
public function get maxFontSize():Number {
return _maxFontSize;
}

// Define public setter method.
public function set maxFontSize(value:Number):void {
if (value <= 30) {
_maxFontSize = value;
} else _maxFontSize = 30;
// Create event object.
var eventObj:Event = new Event("maxFontSizeChanged");
dispatchEvent(eventObj);
}

Работа с цепочками связываемых свойств.

Следующий пример показывает довольно длинную цепочку связываемых свойств:
<mx:Text id="myText" text="{user.name.firstName.text}"/>

Для того, чтобы механизм связывания данных поймал изменения свойства text, достаточно сделать свойство text связываемым. Однако, если необходимо присвоить новое значение какому-либо элементу цепочки на этапе выполнения, то все они должны быть связываемыми. С другой стороны, изменение любого из элементов приведет к неспособности механизма связывания отслеживать изменение свойства text.
В случае работы с такими цепочками, можно пользоваться методами BindingUtils.bindProperty() или BindingUtils.bindSetter() .
Пример использования bindProperty():
bindProperty(myText, 'text', user, ["name","firstName","text"]);

Здесь представлена цепочка в виде ["name","firstName","text"] относительно объекта user. При этом user не является элементом цепочки.
В MXML цепочка связываемых свойств всегда задается относительно this:
bindProperty(myText, 'text', this, ["user", "name","firstName","text"]);

Deep Linking. Flex

Новая (ОЧЕНЬ ВАЖНАЯ) фича Flex 3, предоставляющая Flex-приложению возможность управлять данными URL с использованием якорей "#" (также именуемая псевдо-URL).
Эта возможность позволяет контролировать изменения URL адресной строки броузера, а также вносить в него изменения.

Новые классы:
mx.events.BrowserChangeEvent;
mx.managers.IBrowserManager;
mx.managers.BrowserManager;
mx.utils.URLUtil;
Application.historyManagementEnabled

Пример:
Deep Link 1
Deep Link 2

DataGrid и AdvancedDataGrid. Flex

Стоит задача: список, элементы которого могут содержать изображения, разветвляться.
Из всех доступных компонентов, мне показался наиболее подходящим AdvancedDataGrid.

Хочется посмотреть, как люди его используют.
Покопаем интернет.

В процессе тестирования выяснилось (и сразу вспомнилось, что об этом говорилось на последнем съезде RAFPUG), что advancedDataGrid не является бесплатным компонентом. Об этом, собственно, вещает надпись на компоненте в конечном Flex-приложении. Кроме того, в подобном преступлении был уличен и компонент OLAPDataGrid.

Пока оставим этот компонент в покое и перейдем к компоненту попроще - DataGrid.

Отличный пример использования списка с изощрениями приводится здесь. Я, пожалуй, этот код запомню: Представление компонентов в виде списка. Flex. Здесь есть над чем задуматься - первые же пробы показали, что этим методом можно в виде списка представлять всё что угодно.

После нескольких эксперементов по применению этого кода к DataGrid картина совсем прояснилась.

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

Фокус на кастомном Flex-компоненте

Внедряется кастомный компонент, в котором задействована клавиатура.
После того, как последовательность интерфейсов доходит до экрана с этим компонентом, он активируется. Но не принимает события от клавиатуры. Необходимо установить на него фокус:
Либо добавить в параметры MXML-тега:
creationComplete="setFocus();"

Либо инициализировать в скрипте:
this.[component_name.]setFocus();

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

Параметры командной строки ASDoc

-doc-classes path-element [...] - cписок документируемых классов. Эти классы должны располагаться в директории с исходным кодом. Этот параметр используется по умолчанию.

-doc-namespaces uri manifest - список URI (пространства имен), классы которых должны быть документированы. Эти классы должны располагаться в директории с исходным кодом. Необходимо указать URI и место размещения файла, определяющего содержимое пространства имен.

-doc-sources path-element [...] - список документируемых файлов. Если в списке указана директория, происходит рекурсивная обработка ее файлов.

-exclude-classes string - список классов, которые не будут включены в документацию. Необходимо указывать имя каждого усключаемого класса. Аналогично работает тег @private, указанный при комментировании класса - класс не документируется.

-exclude-dependencies true/false - определяет, будут ли документироваться зависимости, найденные компилятором. Если указано true - зависимости вводимых классов не будут документироваться. По умолчанию false.

-footer string - текст в нижней части HTML-страницы.

-left-frameset-width int - целое число, устанавливающее ширину левого фрейма страницы документа. Можно менять это значение с тем, чтобы подстроить фрейм под ширину имен пакетов классов. По умолчанию 210 пикселей.

-main-title "string" - текст в верхней области HTML-страницы. По умолчанию "API Documentation".

-output string - директория, в которой будут размещаться файлы документации. По умолчанию "asdoc-output".

-package name "description" - текст, документирующий пакет классов. Этот параметр можно указывать повторно для описания множества пакетов классов. Например:

asdoc -doc-sources my_dir -output myDoc -package com.my.business "Contains business classes and interfaces" -package com.my.commands "Contains command base classes and interfaces"

-templates-path string - путь к директории с шаблонами ASDoc-документации. По умолчанию, используются шаблоны, размещенные в поддиректории "asdoc/templates" каталога, где установлен ASDoc. Директория содержит файлы HTML, CSS, XSL и файлы изображений, используемы для создания документации.

-window-title "string" - текст на верхней панели окна интернет-браузера. По умолчанию "API Documentation".

Типичная строка для генерирования ASDoc-документации:

asdoc -doc-sources "Путь к файлам исходного кода" -main-title "Название проекта" -output "Каталог с документацией"

* * *

Столкнулся с проблемой. Код [Event(name="buttonDown", <strong>type="mx.events.FlexEvent"</strong>)] вызывает ошибку компиляции ASDoc. После того, как убрал теги <strong> всё прокатило.

вторник, января 22, 2008

О том, как Flash Player воспроизводит видео MP4, Quicktime, и даже музыку из вашего iPod.

Все говорят, "Вот, Flash Player воспроизводит кучу видео-кодеков". А давайте проверим?
Первым делом лезем в Гугл и по первой же ссылке попадаем на Flash-Ripper.
Прочитав, первое желание пойти и посмотреть этот "Арал Балкан: FAQ по Adobe Flash Player H.264 support". Вопросы нас интересующие:

  • Будет ли воспроизводить FP9 не-FLV файлы или расширения?
    Да. Стандартные контейнеры MPEG-4, содержащие видео и аудио данные закодированные H.264/AAC, MP4, M4V, M4A, MOV, Mp4v, 3gp, 3g2.

В ответах находим интересную ссылку: http://www.debit.nl/video/. Здесь на странице, SWF воспроизводит видео MOV. Ага, раз у нас играется, значит с плеером всё в порядке. К слову, это видео H.264.

Попробуем воспроизвести этот файл своими средствами. Создаем в Flash CS проект AS3 с FLVplayback. Вызываем:


Локальная политика безопасности - только интернет, запускаем опубликованый HTML, смотрим. Пошла загрузка. Молчание.
Скачиваем MOV, пытаемся воспроизвести локально. Компилируем, запускаем.
Выкидывает исключение:
VideoError: 1005: Invalid xml: URL: "Video/BookofSecrets.mov" No root node found; if url is for an flv it must have .flv extension and take no parameters
Аналогичные действия с AS2 - проектом вообще вызывали ошибки и зависания.
Значит FLVPlayback не может воспроизводить другие видео-файлы.

По совету коллеги, создаю Flex-проект и перетаскиваю компонент VideoDisplay. В свойствах source указываем URL и - вуаля, всё играется. Локальный файл не позволяет воспроизвести политика безопасности. Но с этим мы боремся легко (гугл рулит) - добавляем параметр -use-network=false в Project -> Properties -> Flex Compiler -> Additional compiler arguments.

Возникает вопрос - были утверждения: что Flash Player 9 MovieStar может легко воспроизвести видео любым способом, даже непосредственно самим проигрывателем, и старые проекты откомпилированные еще под 7-ю версию не будут иметь проблем. А почему же не получается? Почему только флекс-компонент VideoDisplay способен воспроизвести такое видео? Что же не так?

* * *

Попробовал пример из Flash CS3 Help Actionscript 3.0 Components для класса Video. Воспроизводит! Для него вопрос снимается.

* * *

А вот компонент Media Display Actionscript 2.0 наш MOV не воспроизводит.

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

Не работает скрипт в TimeLine. Нашлось объяснение. AS3

Наткнулся на решение проблемы описаной мной здесь.

На Labs.Adobe.com смотреть обсуждение "stop() not being called within movieclip".

Ответ на вопрос звучит так: Did you apply the Flex 2.0.1 patch for Flash CS3? The problem you are describing is fixed in that patch.

Как лучше постить код в 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 мБ. Теперь всё встало на свои места. Прелоадер аккуратно отрабатывает объем и затем отображается картинка! Всё дело было в слишком быстром интернете.

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

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

Теги ASDoc. AS3

Теги ASDoc

@copy reference - копирует ASDoc комментарий из reference. Копируется основное описание и теги @param и @return. Остальные теги не копируются.
Пример: @copy #stop, @copy MovieClip#stop

@default value - указывает значение по умолчанию value для свойства, стиля или эффекта.
Пример: @default 0xCCCCCC

@eventType package.class.CONSTANT - комментарий для тега метаданных [Event]. Описывает константу, которая определяет значение свойства Event.type объекта event, ассоциированного с событием.

@eventType String - комментарий для констатны события. Указывается перед определением константы события и определяет название события. Если тег не указывается, комментарий констатны не заносится в описываемый класс.

@example exampleText - вставляет пример в текущее описание, при этом применяет к тексту кода особый стиль и генерирует заголовок. Сам код заключается в теги <listing version="3.0"></listing>. Код будет расположен в серой прямоугольной прокручиваемой области с сохранением пробельных символов.
Пример: @example The following code sets the volume level for your sound: <listing version="3.0"> var mySound:Sound = new Sound(); mySound.setVolume(VOL_HIGH); </listing>

@exampleText string - используется во внешних файлах с примерами, на которые осуществляется ссылка из тега @example. Этот комментарий должен располагаться в начале, перед первой строкой или в конце - ниже последней строки примера. Во внешних файлах примеров допустимо указывать только один комментарий в начале и один в конце.
Пример: /** * This text does not appear * in the output. * @exampleText But this does. */

@inheritDoc - используется для комментирования перекрываемых свойств и методов класса-потомка. При этом, в описание класса-потомока копируется комментарий из класса-предка, или из интерфейса, который реализуется этим классом-потомком. Копируется только содержимое тегов @param и @return. Остальные теги игнорируются. При формировании комментария для этого тега, соблюдается следующий порядок:
1. Интерфейсы, используемые описываемым классом (в свободном порядке) и все их базовые интерфейсы.
2. Прямой предок класса.
3. Интерфейсы, используемые классом прямого предка и все их базовые интерфейсы.
4. Повторяются п. 2 и 3 до тех пор, пока не будет достигнут класс Object.
Пример: @inheritDoc

@internal text - внутренний комментарий, который не будет включен в документацию.
Пример: @internal Please do not publicize the undocumented use of the third parameter in this method.

@param paramName description - добавляет комментарий, описывающий метод с именем paramName.
Пример: @param fileName The name of the file to load.

@private - исключает внесение комментируемого элемента в документацию.
Пример: @private

@return description - добавляет в описание метода раздел Return - комментарий касательно возвращаемого значения. Возвращаемый тип определяется ASDoc автоматически.
Пример: @return The translated message.

@see reference [displayText] - добавляет в описание метода раздел See Also - ссылка на описание элемента класса.
Пимер: @see flash.display.MovieClip

@throws package.class.className description - документирует ошибку (исключение), которую может генерировать метод.
Пример: @throws SecurityError Local untrusted SWFs may not communicate with the Internet.


Не ASDoc теги

Я не нашел эти теги в Adobe LiveDocs, но люди их пользуют.

@author - автор кода. Пример @author Name
@version - версия кода. Пример @version 3.15
@langversion - языковая версия. Пример @langversion ActionScript 3.0
@playerversion - версия Flash Player. Пример @playerversion Flash 8


Примеры использования тега @see:

@see "Just a label" - текстовая строка
@see http://www.cnn.com - ссылка на внешний веб-сайт
@see package-detail.html - ссылка на локальный HTML-документ
@see Array - класс верхнего уровня
@see AccessibilityProperties - пакет
@see flash.display.TextField - класс TextField в пакете flash.display
@see Array#length - свойство класса верхнего уровня Array
@see flash.ui.ContextMenu#customItems - свойство класса ContextMenu из пакета flash.ui
@see #updateProperties() - метод в описываемом классе
@see Array#pop() - метод класса верхнего уровня Array
@see flash.ui.ContextMenu#clone() - метод класса ContextMenu из пакета flash.ui
@see global#Boolean() - метод пакета верхнего уровня global
@see flash.util.#clearInterval() - метод из пакета flash.util

Относительно правил ASDoc-комментирования смотреть списанное из чужой тетради.

PS: Наконец решил расставить все точки над Ы и правильно комментировать свой код.

* * *

Другие замеченные теги

@mxml
@includeExample
@event

вторник, января 15, 2008

Вторая встреча RAFPUG. Дети - наше будущее.

Владелец "Быстроупака" был чрезвычайно доволен. "Красиво составлено, - решил он, - под таким соусом и деньги дать можно. В случае удачи - почет! Не вышло - мое дело шестнадцатое. Помогал детям, и дело с концом".
Двенадцать стульев. Илья Ильф, Евгений Петров

Вторая встреча состоялась 14 января 2008. Несколько ключевых моментов: комьюнити, доклады, место проведения, дети.

Место проведения

Место нашли быстро, благодаря фотографиям, размещенным в анонсе. Иначе, можно было бы долго плутать между длинных заборов. Итак, к 17 часам мы оказались в заведении, именуемом "Московская физико-математическая школа №2". Кстати, впечатление вполне положительное - всё чисто, ухожено и культурно. Рядом со входом уже курили участники встречи в том числе Рост, Иван, Константинер, Таня и другие сотоварищи. Поздоровались - уухх руку не буду неделю мыть!

Несмотря что это только вторая встреча флашеров, а лица все знакомые и как-то всё по-доброму. Проходим в актовый зал - народу в этот раз явно больше. Сидят дети - по-видимому учащиеся в этой школе.

Доклады

После вступительного слова о пользе и благодарности компании Adobe, микрофон взял Andrew Shorten. Несколько раз оглушенный высокочастотными писками и скрипами из динамиков, он произнес хвалебную речь новым достижениям Adobe в области RIA. Доклад сопровождался переводом, что было хорошо для понимания, но убийственно для времени проведения мероприятия. Зато дети не скучали и внимательно слушали. После доклада много времени убилось на вопросы слушателей, в принципе не сильно важные и интересные.
Лично для меня, доклад внес ясность в некоторые вопросы касательно AIR. В остальном - просто обновил и подкорректировал общую картину продукции Adobe.

После буфета, последовал доклад про Flex 3. На этот раз обошлись без перевода и мне пришлось включить свой английский. Дети начали потихоньку линять.
Andrew на примерах рассказал о том, как сделать компонент, создать скин для компонента, показал новые фичи. Сильно подпортил картину тормозной компьютер, за который Andrew постоянно извинялся и краснел. Кроме того, примеры были уже "заготовлены", что смотрелось менее познавательно и убедительно чем в докладе Артемия Малкова на первой встрече. Но в итоге лично я остался доволен. Нас собрали, бесплатно рассказали о важных и познавательных вещах, да еще и покормили.

После нескольких вопросов-ответов, слово взял Enrique Duvos. Доклад читался на английском с испанским акцентом. Этот чертов испанец, в свойственной им манере, так зашустрил, что пришлось включить свой быстрый английский. А он у меня еще не доделан. Поэтому, информация усваивалась частично и большей частью читалась с экрана. Но на экране тоже было всё мелко и с нашего ряда неразборчиво.
И всё же, урывками, я получил общее представление о том, какие продукты являются open-source, какие нет, чем это всем грозит и как всё это замечательно. Дата-сервисы дались труднее. Впечатлила демонстрация синхронной работы двух флекс-приложений, причем, синхронизация осуществлялась мгновенно посредством сокетов через веб-сервис.
Почти все дети ушли. Остались самые стойкие. Точнее стойким был один. Он сидел в ряду перед нами и внимательно слушал. Его вид настолько меня впечатлил, что мне даже за себя стало стыдно что я половину читаемого не понимаю... Рядом дальше сидели два его товарища. Нет - они полулежали, полукрутились, полуспали и упирались лбами в спинки впереди стоящих стульев. Короче, создавали контраст, что вселяло еще больше уважения к первому стойкому. Не... если б мне обломился приз на розыгрыше, я б наверное отдал приз ему.

Перекусив парой-тройкой булок в буфете, мы перешли к заключительной части. Заключительная часть была сильно скомкана. И не удивительно. Уже был 10й час. Constantiner, уложившись в 10 минут поведал о RIA. Что можно рассказать о RIA за 10 минут? Только общие фразы, которые в основном нам всем уже известны. Жаль, что мероприятие началось так поздно - я убежден, что Костя хотел нам рассказать гораздо больше и интереснее.
Иван Дембицкий еще раз доказал свою компетентность и заслуженное уважение во flash-сообществе. Как я краем уха слышал без подготовки, Ваня выразил наше общее настроение, по сути, подведя резюме первой встречи.
Артемий Малков завершил выступления. Мысль его была направлена на внедрение flash в систему образования. Презентация его была украшена забавной анимацией, наглядно показывающей, как здорово на флэш смотрятся физические опыты. Однако, большое черное пятно в левом нижнем углу выглядело на экране проектора как тень от чьей-то прострелянной головы, что было еще забавнее.

В конце мероприятия провели розыгрыш призов. Все участники заполнили анкеты, из которых и выбирались счастливчики. Призы были действительно ценные - коробки с Flash CS3 (или Master Collection?), Flex Professional, iPhone nano, ну и по мелочи - рюкзаки. Правда призы застряли где-то по дороге, но обещали что их доставят почтой.
Мы-то знаем для чего нужен розыгрыш в конце мероприятия - чтоб народ до конца досидел и анкеты заполнил. Лишняя мотивация - перестраховались что ли? Сомневаюсь, что кто-то сидел ради призов.

А вообще, ребята из Adobe вызвали только положительные эмоции. Веселые, симпатичные парни, вызывающие доверие и располагающие к разговору. Всё шутили, но на вопросы отвечали довольно серьезно. И не удивительно - специально обученые бойцы Adobe.
Кто-то говорил, что будет Суми Лим (глобализейшн менеджер). Но, то ли я ее не заметил, то ли я что-то не догнал, то ли ее не было.

Впечатления

  • Жаль что поздно начали. Во второй половине дня уже мозг плохо воспринимает информацию и зовут домашние дела. И времени явно не хватило.
  • Доклады, несмотря на многие недостатки, оказались очень ценными и я нисколько не жалею о потраченном времени.
  • Идею преподавать программирование на Flash в школах лично я поддерживаю, т.к. у флэша есть одно главное преимущество - с ним интересно работать. Детям это будет увлекательнее чем бэйсик. Кроме того, в комплексе могут быть даны основы графики и анимации.
    Но есть одно НО. Преподавать надо соблюдая правила программирования, чтобы не запудрить детям мозг нетипизированными переменными, глобальными _root-ами и другими вредными особенностями ActionScript. А еще точнее - преподавать надо не ActionScript, а программирование согласно стандарта ECMAScript. Иначе можно "попортить" наших программистов.
  • Насчет вопроса о преподавании Flex в ВУЗах сомневаюсь. Точнее, преподавать нужно, но факультативно. Пусть учащиеся сами выбирают кем они хотят быть и на чем хотят программировать. Создавать факультет Flex-разработчиков или кафедру Flash, на мой взгляд, мало кто согласится. Это узкая специализация. Хотя, кто знает... RIA-специалист, возможно вполне реальная специальность. Но она много чего в себя должна включать. А Flash/Flex-разработка лишь как составляющая.
    Вызвало недоумение утверждение Артемия Малкова по поводу преподавания Flash/Flex - (по памяти) - "Если кто-то рисует хорошо - будет рисовать, кто-то похуже - будет программировать". Как-то однобоко. А если и программировать не умеет? В расход пускать?
  • Ждем следующей встречи!

* * *

Поправки.

По-видимому до нашего ряда иноязычная речь дошла с искажениями и вот, появились уточнения и коррекции. Призы - Flex Builder 3 Professional, Creative Suite 3 Web Premium, iPod Nano.

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

uint лучше не использовать для счета. AS3

В обсуждении "AS3: uint на много медленнее, чем Number" выясняется, что тип uint лучше не использовать для счетных целей, если конечно нет особой необходимости. Сам с собой он складывается ужасно, с Number еще ужаснее.

Adobe отдыхает




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

Осваиваем Papervision3D. Часть III. Примеры

Продолжаем вгрызаться в Papervision 3D.
Для тестирования я выбрал пример "Panorama" из папки "examples". Кстати, попутно еще раз убедился в пользе SVN: скопировав папку с примером в рабочий каталог, я скопировал находящуюся в ней папку ".svn" - теперь в любое время, я могу выбором из контекстного меню проводника легко обновить файлы прямо с сервера SVN-репозитория. Чертовски удобно - пора ставить SVN-сервер!

Создаю во FlashDevelop проект типа "Flash IDE Project". В свойствах проекта, в "Classpaths" указываю путь к классам Papervision3D "...\as3\trunk\src". Это нам нужно для того, чтобы работала проверка ошибок, подстановка и другие удобства. Как только классы подцепились, в панели "Task Panel" FlashDevelop появился список задач TODO, что говорит о незавершенности и бурном развитии проекта.
Теперь надо указать путь к классам во Flash IDE. В Getting Started FAQ нам советуют установить путь в свойствах среды: "Edit -> Preferences -> Actionscript -> Actionscript 3.0 settings -> Classpath". Пожалуй не буду обобщать и укажу путь для моего конкретного FLA файла в "Publish settings -> Actionscript Settings -> Classpath". Кстати, там уже есть путь к классам, но только относительный, а раз мы скопировали в другую папку, то, конечно, неправильный.
Запускаем проект - всё компилируется без ошибок, запускается панорама - мы внутри куба, на стенах которого надписи. Попробуем что-нибудь изменить. Например, мне не нравится качество отображения надписей. Всё из-за того, что текстуры маленькие и качество сцены установлено в LOW. Увеличиваем размер одной из текстурок - например, та что "BOTTOM". Хе, на размер 3000 выскочило исключение. Ладно, поставим 2000. Забавно натягивает.
Заметил хитрый ход: изменение качества сцены сильно не меняет картины, однако, ресурсов процессора потребляется заметно меньше.
Продолжаем смотреть примеры. В общих чертах - создается сцена, создается камера, создаются материалы для объектов, создаются объекты и добавляются в сцену, выставляются параметры и по ENTER_FRAME осуществляется управление сценой и ее перерисовка.

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

среда, января 09, 2008

Осваиваем Papervision3D. Часть II. Установка

Следуем Getting Started FAQ -> Getting started walkthrough.
Качаем и устанавливаем SVN-клиент. Об этом подробно изложено здесь: "Установка SVN-клиента TortoiseSVN". Тут же описан процесс скачивания SVN-репозитория.
В итоге, мы имеем каталог с классами Papervision3D.

Порыв интернет, нашел следующую информацию по серверу Subversion:
Здесь пишут, что:
"Большинство людей создают папку trunk для поддержки "основной линии" разработки, папку branches для копий ветвей, и папку tags для копий меток. Если хранилище содержит только один проект, тогда часто создают их как папки верхнего уровня."
Здесь пишут, что:
"Структура проекта может быть произвольной, но общепринято создавать три основных каталога: branches – для веток, tags – для тегов проекта и trunk – непосредственную рабочую область для коммитов".
На Wikipedia можно почитать про Subversion в общих чертах.

Кстати, попался на глаза блог Установка и настройка Subversion. Нам это еще пригодится.

Итак, базовая структура репозитория создается из директорий trunk, tags, и branches.

На сколько я понял, структура SVN Papervision3D следующая:

  • as2 - С ней всё ясно: "\as2\trunk\" содержит классы финальной версии для AS2, ее документацию и примеры.
  • as3 - Здесь в "\as3\trunk\" лежит финальная версия для AS3. В "\as3\tags\", очевидно, предыдущая версия.
  • branches - Здесь разрабатываемые/тестируемые/альфа/бета версии. По всей видимости, нас интересует "\branches\GreatWhite\" - та что Papervision3D 2.0 GreatWhite.

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

Продолжаем изучать полученные материалы. Пока не будем лезть в последнюю версию и поработаем с той, что лежит в "trunk" - "Beta 1.7" (я узнал это, открыв и просмотрев файл "Papervision3D.as").

Смотрим примеры.

Магическое число 6710886.35. AS2

Интересно, что для пустого клипа getBounds() выдает:
для _root:
yMax=6710886.35
yMin=6710886.35
xMax=6710886.35
xMin=6710886.35
для обычного клипа, почему-то округляет до 6710886.4.

Любопытно, что если это число перевести в HEX, получается 666666... Мистика.

Осваиваем Papervision3D. Часть I. Обзор ресурсов

Итак, свершилось. Добрались, наконец, до Papervision3D.

Для начала порыскаем по сайту. Посмотрим, для начала, последние проекты с использованием этой технологии и вдохновимся.
Первый, интересный для нас раздел - Downloads. Судя по датам, всё, что здесь размещено уже старовато - последняя версия 1.5, дата последнего апдейта - Jul 25. Хотя, в новостях уже можно видеть декабрьский анонс Papervision3D 2.0 Alpha - Great White. Судя по отзывам, пока ни у кого не возникло существенных проблем использования последних версий. Только восторги и благодарности. Что ж, значит нам туда дорога.
Дальше, поглядим-ка, что тут на форуме. Активность здесь неслабая.
Раздел "Getting Started" - это что нам и надо. Смотрим Documentation. Как и следовало ожидать, скупо документированный ASDoc. Что радует, на первый взгляд - структура прозрачна, а количество пакетов и классов вполне обозримо.
Ссылка Cheatsheet открываться не захотела.
Tutorials и Getting Started FAQ, собственно,ведут на Wiki, где нам и предстоит остановиться в дальнейшем.
Еще один интересный раздел - "Recommended tools". Здесь нам рекомендуют пользоваться FlashDevelop (что мы, собственно и делаем), Fuse Kit - пока непонятно зачем (движок анимационных эффектов на AS2, а 3-я версия этого продукта, по всей видимости, пока готовится), Xray - утилита для просмотра снэпшота текущего состояния flash-приложения. Мда, по-видимому это просто партнерские ссылки.

Ладно, идем смотреть Wiki.
В разделе Getting Started FAQ для нас наиболее интересна информация "Getting started walkthrough" - подробное описание скачивания и установки Papervision3D. Этот процесс мы рассмотрим во второй части изысканий.
Разделы FAQ, Tutorials и Examples оставим для 3-й части.
Ссылки из "Content creation" посвящены созданию 3D-контента. Здесь без 3D-специалиста мне не обойтись, т.к. сам я имею отдаленное представление о 3D-моделировании - пусть этим занимаются другие. Подсуну ему вот эту ссылочку: COLLADA, чтоб у него было чем экспортить для меня модели.
Ссылки "Showcase" дают мало полезного - старые демки, сайты c SWF по 20Mb и т.п.

Итак, пора приступать к установке и тестированию Papervision3D.