Как известно, дублировать как в AS2 клипы уже нельзя - нет такого метода. Странно конечно, и зря. В шаблонной структуре приложения это было бы очень полезно.
Но в AS3 есть множество средств, которыми можно это сделать. Для начала, порыщем в Google.
Duplicate Movie Clip Action Script 3 (взято у Senocular, в котором есть этот исходник).
Этот метод уже стал классикой, судя по тому, как много на него ссылается блогов и форумов. Он также описан на Flashere. Идея такова: извлекается класс исходного дисплей-объекта var targetClass:Class = Object(target).constructor;
, инстанцируется, и в него переносятся основные свойства исходного дисплей-объекта.
as3 duplicate DisplayObject. Здесь класс исходного дисплей-объекта получается аналогичным образом. Отличие лишь в том, что передаваемые свойства автоматически извлекаются посредством рефлексии - метода describeType
.
Creating Class Instances from a DisplayObject in AS3. Здесь имя класса получается более хитрым способом - из строки, возвращаемой getQualifiedClassName
. Затем, getDefinitionByName
возвращает класс исходного дисплей-объекта.
Других, более вменяемых способов решения я пока не нашел. Почему "более вменяемых"? Да потому, что все эти способы имеют одно очень существенное ограничение. Они не дублируют произвольный дисплей-объект. То есть дублируемый объект должен обязательно иметь обозначенное в Linkage имя класса. Если мы протрейсим имя класса произвольного клипа, это будет MovieClip или SimpleButton, а инстанцируя их, мы получаем просто пустые клипы.
Таким образом, дублировать клип вышеперечисленными способами нельзя если клип не имеет имени класса в Linkage.
Это еще полбеды. Ведь мы всегда можем просто взять, да и указать это имя.
Но.
А если мы внедряем в наше приложение некий клип при помощи [Embed] , который в дальнейшем надо распарсить и что-то в нем дублировать?
Это что-то мы никогда не сможем дублировать, т.к. никакие Linkage-классы из внедряемой библиотеки не распознаются - они не переносятся в ApplicationDomain.
Кстати, интересное замечание по второму способу с рефлексией: describeType для объектов из внедряемой библиотеки выдает тэги описания свойств как "accessor", в то время как для объектов из подгруженной библиотеки - "variable".
Итак, вывод - универсального решения нет, и выход один - всё делать "ручками". Или я ошибаюсь?
* * *
Спасение пришло с другой стороны: Включение файлов в SWF в виде байтовой последовательности. Проблема внедряемых файлов будет устранена, остальное, в принципе решаемо.
* * *
Да, интуиция поискать по запросу loadBytes
не подвела. Внедрил SWF вышеуказанным способом, загрузил через Loader.loadBytes
. Отлично! Даже фреймовые скрипты работают. Всё как обычный Loader.load
.
Единственная оговорка: Я загружаю классы в ApplicationDomain.currentDomain
. При этом, параметр checkPolicyFile необходимо установить в false:var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
Еще раз спасибо Garbage Collector. Глядя на дату спасительного поста, я понимаю, что здорово отстаю :(.
6 комментариев:
я думаю в "шаблонных проектах" надо делать класс-шаблон и создавать его инстансы, а не дублировать инстансы. немогу представить себе ситуацию, где понадобилось бы прямое дублирование. разде что нарисованный программно шейп.
Я наверное не совсем правильно выразился. Сорри. Да в принципе, я и не говорил "Шаблонный проект". Под "шаблонной структурой приложения" в данном случае следует понимать приложение, работающее с неким шаблоном, подгружаемым извне. То есть "шаблон" - это некий стандарт, которому следует структура внешней флэшки.
Ну вот смотри. Есть шаблонная флэшка. Она грузится/внедряется в приложение. Приложение после ее загрузки/получения сканирует эту флэшку, навешивает на кнопки события, вносит тексты, выставляет другие свойства, создает управляющие классы, поручая им для пользования дисплей-объекты (тобишь клипы).
Так вот, к примеру, один из управляющих классов должен генерить в свой контролируемый клип некоторое количество клипов-деталей.
Откуда ему их взять? Как ему сказать какие клипы-детали он дожен генерить? Задача состоит в том, чтобы сделать это с минимумом завязок на код. Простое и понятное решение - просто кинуть в контролируемый клип "образцы" тех клипов, которые нужно нагенерить. Управляющий класс их сосканирует и еще нагенерит сколько надо. Универсально и понятно для flash-верстальщика.
racer, думаю не стоит пока во AS3 налегать на копирование произвольных мувиков. Во-первых всё уже придумано :-) - сериализация. Во-вторых тут не только мувик нормально продублировать нельзя, но и просто сложный класс (может быть я не прав.. тогда укусите меня).
Есть такой подход, пишу навсякий (если вдруг ты не в курсе):
public static function copy(value: Object): Object
{
var buffer: ByteArray = new ByteArray();
registerClassAlias(getClassAlias(value), value.constructor);
buffer.writeObject(value);
buffer.position = 0;
return buffer.readObject();
}
Такая конструкция требует flash.net.registerClassAlias для всех подклассов, на сколько я понял.
Да с загрузкой swf-а не Loader-ом меня тоже сильно ущимило, как пользователя AS3. Я был просто в недоумении и пребываю в нём до сих пор ). Почему адобовцы пренебрегли в данном случае простыми принципами ООП разделения полномочий. Вобщем конечно косяков хватает. И шарп во многом выглядит привлекательнее, хотябы гарбэджем. Но я делаю скидку на то что первый блин все-таки комом.
Напоследок в тему.. )) пользуйся интерфейсами для подгрузки заранее известного по функциональности мувика (совет я читал от __etc).
Спасибо, foreground. Есть заметки:
> сериализация
Любопытно, код в точности из mx.utils.ObjectUtil.copy() с добавлением registerClassAlias(getClassAlias(value), value.constructor);. Я как раз начал эксперементы с сериализации через ObjectUtil.copy, но безуспешно. Через сериализацию нельзя скопировать объект клипа полностью, т.к. она не предусматривает копирование объектов, на которые ссылаются свойства копируемого объекта. Скопируются просто ссылки. Да, собственно, в хелпе для ObjectUtil.copy написано - предназначен для копирования объектов данных, типа элементов коллекций, а UIComponent так не копируется.
Чтобы копировать сложный класс, нужно рекурсивно пройтись по всем ссылкам и сохранить все вложенные объекты, а затем их опять восстановить. Кроме того, встает вопрос - а если не все ссылки надо копировать? Типа ссылки на root, stage и т.п.
Поэтому, общего решения быть не может.
А Адоби не предусмотрел, а ведь мог бы сделать метод DisplayObject.clone();
>Да с загрузкой swf-а не Loader-ом ...
Ембед с параметром
mimeType="application/octet-stream" - работает превосходно - никакой видимой разницы - зашита SWFка или загружается.
>пользуйся интерфейсами для подгрузки ...
Это есть смысл делать, если нужно подгружать и обрабатывать что-то с программным кодом. Например, некие программные модули, из которых строится приложение или что-то типа плагинов.
В моем случае, меня интересуют абсолютно свободные от этого "недостатка" чисто графические библиотеки. Весь код - в управляющей флэшке. И задача то простейшая - клонирование, которая была решена в AS2 для любого мувика.
2 racer
сори если что )
"Ембед с параметром
mimeType="application/octet-stream" - работает превосходно - никакой видимой разницы - зашита SWFка или загружается."
тут вобще-то я имел ввиду не эмбед, а правильную реализацию лодера. Правильнее было бы отделить процесс декодирования от загрузки, а не делать кучу классов занимающихся одним и тем же.
Эмбед нельзя сконфигурировать через отдельный файл настроек насколько я знаю .. хотя было бы неплохо.
Попробуй все-таки несколько registerClassAlias для подклассов, перед самим копированием. У меня получалось с URLRequest кажется.
аа. ..да для BitmapData вроде не пашет.
Отправить комментарий